Merge branch 'nightly'
Conflicts: INSTALL
							
								
								
									
										34
									
								
								EVENTS.txt
									
									
									
									
									
								
							
							
						
						@@ -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
 | 
					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
 | 
					StartPrimaryNav: Showing the primary nav menu
 | 
				
			||||||
- $action: the current action
 | 
					- $action: the current action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1444,6 +1451,9 @@ StartResizeImageFile: Hook to resize an image and output it to a file. No matchi
 | 
				
			|||||||
- $outpath:   string with output filepath
 | 
					- $outpath:   string with output filepath
 | 
				
			||||||
- $box:       array with size ('width', 'height') and boundary box('x', 'y', 'w', 'h').
 | 
					- $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).
 | 
					StartShowAttachmentRepresentation: Attachment representation, full file (or in rare cases thumbnails/previews).
 | 
				
			||||||
- $out:     HTMLOutputter class to use for outputting HTML.
 | 
					- $out:     HTMLOutputter class to use for outputting HTML.
 | 
				
			||||||
- $file:    'File' object which we're going to show representation for.
 | 
					- $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.
 | 
					EndNotifyMentioned: During notice distribution, we send notifications (email, im...) to the profiles who were somehow mentioned.
 | 
				
			||||||
- $stored:         Notice object that is being distributed.
 | 
					- $stored:         Notice object that is being distributed.
 | 
				
			||||||
- $mentioned_ids:  Array of profile IDs (not just for local users) who got mentioned by the notice.
 | 
					- $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
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										238
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						@@ -6,13 +6,16 @@ TABLE OF CONTENTS
 | 
				
			|||||||
* Installation
 | 
					* Installation
 | 
				
			||||||
    - Getting it up and running
 | 
					    - Getting it up and running
 | 
				
			||||||
    - Fancy URLs
 | 
					    - Fancy URLs
 | 
				
			||||||
 | 
					    - Themes
 | 
				
			||||||
 | 
					    - Private
 | 
				
			||||||
 | 
					* Extra features
 | 
				
			||||||
    - Sphinx
 | 
					    - Sphinx
 | 
				
			||||||
    - SMS
 | 
					    - SMS
 | 
				
			||||||
    - Queues and daemons
 | 
					 | 
				
			||||||
    - Themes
 | 
					 | 
				
			||||||
    - Translation
 | 
					    - Translation
 | 
				
			||||||
 | 
					    - Queues and daemons
 | 
				
			||||||
 | 
					* After installation
 | 
				
			||||||
    - Backups
 | 
					    - Backups
 | 
				
			||||||
    - Private
 | 
					    - Upgrading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Prerequisites
 | 
					Prerequisites
 | 
				
			||||||
=============
 | 
					=============
 | 
				
			||||||
@@ -41,10 +44,10 @@ functional setup of GNU Social:
 | 
				
			|||||||
- php5-curl     Fetching files by HTTP.
 | 
					- php5-curl     Fetching files by HTTP.
 | 
				
			||||||
- php5-gd       Image manipulation (scaling).
 | 
					- php5-gd       Image manipulation (scaling).
 | 
				
			||||||
- php5-gmp      For Salmon signatures (part of OStatus).
 | 
					- php5-gmp      For Salmon signatures (part of OStatus).
 | 
				
			||||||
- php5-intl     Internationalization support, part of core.
 | 
					- php5-intl     Internationalization support (transliteration et al).
 | 
				
			||||||
- php5-json     For WebFinger lookups and more.
 | 
					- php5-json     For WebFinger lookups and more.
 | 
				
			||||||
- php5-mysqlnd  The native driver for PHP5 MariaDB connections. If you
 | 
					- 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
 | 
					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
 | 
					Arch Linux, PHP is compiled with support for most extensions but they
 | 
				
			||||||
@@ -69,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
 | 
					You may also experience better performance from your site if you configure
 | 
				
			||||||
a PHP cache/accelerator. Most distributions come with "opcache" support.
 | 
					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
 | 
					Installation
 | 
				
			||||||
============
 | 
					============
 | 
				
			||||||
@@ -131,9 +134,9 @@ especially if you've previously installed PHP/MariaDB packages.
 | 
				
			|||||||
   writeable by the Web server group, as noted above.
 | 
					   writeable by the Web server group, as noted above.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
5. Create a database to hold your site data. Something like this
 | 
					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
 | 
					   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,
 | 
					   the database with another program. You can name it whatever you want,
 | 
				
			||||||
@@ -147,17 +150,17 @@ especially if you've previously installed PHP/MariaDB packages.
 | 
				
			|||||||
   database. If you have shell access, this will probably work from the
 | 
					   database. If you have shell access, this will probably work from the
 | 
				
			||||||
   MariaDB shell:
 | 
					   MariaDB shell:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       GRANT ALL on gnusocial.*
 | 
					       GRANT ALL on social.*
 | 
				
			||||||
       TO 'gnusocial'@'localhost'
 | 
					       TO 'social'@'localhost'
 | 
				
			||||||
       IDENTIFIED BY 'agoodpassword';
 | 
					       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
 | 
					   to your preferred new database username and password. You may want to
 | 
				
			||||||
   test logging in to MariaDB as this new user.
 | 
					   test logging in to MariaDB as this new user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
7. In a browser, navigate to the GNU Social install script; something like:
 | 
					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
 | 
					   Enter the database connection information and your site name. The
 | 
				
			||||||
   install program will configure your site and install the initial,
 | 
					   install program will configure your site and install the initial,
 | 
				
			||||||
@@ -171,55 +174,100 @@ Fancy URLs
 | 
				
			|||||||
----------
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
By default, GNU Social will use URLs that include the main PHP program's
 | 
					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
 | 
					It's possible to configure the software to use fancy URLs so it looks like
 | 
				
			||||||
look like this:
 | 
					this instead:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    http://example.net/gnusocial/index.php?p=gnusocial/fred
 | 
					    https://social.example.net/fred
 | 
				
			||||||
 | 
					 | 
				
			||||||
It's possible to configure the software so it looks like this instead:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    http://example.net/gnusocial/fred
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
These "fancy URLs" are more readable and memorable for users. To use
 | 
					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
 | 
					fancy URLs, you must either have Apache 2.x with .htaccess enabled and
 | 
				
			||||||
mod_rewrite enabled, -OR- know how to configure "url redirection" in
 | 
					mod_rewrite enabled, -OR- know how to configure "url redirection" in
 | 
				
			||||||
your server (like lighttpd or nginx).
 | 
					your server (like lighttpd or nginx).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Copy the htaccess.sample file to .htaccess in your StatusNet
 | 
					1. See the instructions for each respective webserver software:
 | 
				
			||||||
   directory.
 | 
					    * For Apache, inspect the "htaccess.sample" file and save it as
 | 
				
			||||||
 | 
					        ".htaccess" after making any necessary modifications. Our sample
 | 
				
			||||||
2. Change the "RewriteBase" in the new .htaccess file to be the URL path
 | 
					        file is well commented. 
 | 
				
			||||||
   to your GNU Social installation on your server. Typically this will
 | 
					    * For lighttpd, inspect the lighttpd.conf.example file and apply the
 | 
				
			||||||
   be the path to your GNU Social directory relative to your Web root.
 | 
					        appropriate changes in your virtualhost configuration for lighttpd.
 | 
				
			||||||
   If you are installing it in the root directory, leave it as '/'.
 | 
					    * For nginx and other webservers, we gladly accept contributions of
 | 
				
			||||||
 | 
					        server configuration examples.
 | 
				
			||||||
3. Add, uncomment or change a line in your config.php file so it says:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
					       $config['site']['fancy'] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You should now be able to navigate to a "fancy" URL on your server,
 | 
					You should now be able to navigate to a "fancy" URL on your server,
 | 
				
			||||||
like:
 | 
					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
 | 
					Themes
 | 
				
			||||||
the server first.
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If it doesn't work, double-check that AllowOverride for the GNU Social
 | 
					As of right now, your ability change the theme is limited to CSS
 | 
				
			||||||
directory is 'All' in your Apache configuration file. This is usually
 | 
					stylesheets and some image files; you can't change the HTML output,
 | 
				
			||||||
/etc/httpd.conf, /etc/apache/httpd.conf, or (on Debian and Ubuntu)
 | 
					like adding or removing menu items, without the help of a plugin.
 | 
				
			||||||
/etc/apache2/sites-available/default. See the Apache documentation for
 | 
					 | 
				
			||||||
.htaccess files for more details:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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
 | 
					Sphinx
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
@@ -284,7 +332,21 @@ For this to work, there *must* be a domain or sub-domain for which all
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
       $config['mail']['domain'] = 'yourdomain.example.net';
 | 
					       $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
 | 
					Queues and daemons
 | 
				
			||||||
------------------
 | 
					------------------
 | 
				
			||||||
@@ -346,16 +408,13 @@ separate server is probably a good idea for high-volume sites.
 | 
				
			|||||||
   .htaccess file, but make sure that your config.php file is close
 | 
					   .htaccess file, but make sure that your config.php file is close
 | 
				
			||||||
   to, or identical to, your Web server's version.
 | 
					   to, or identical to, your Web server's version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3. In your config.php files (both the Web server and the queues
 | 
					3. In your config.php files (on the server where you run the queue
 | 
				
			||||||
   server!), set the following variable:
 | 
					    daemon), set the following variable:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       $config['queue']['enabled'] = true;
 | 
					 | 
				
			||||||
       $config['queue']['daemon'] = true;
 | 
					       $config['queue']['daemon'] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   You may also want to look at the 'daemon' section of this file for
 | 
					   You may also want to look at the 'Queues and Daemons' section in
 | 
				
			||||||
   more daemon options. Note that if you set the 'user' and/or 'group'
 | 
					   this file for more background processing options.
 | 
				
			||||||
   options, you'll need to create that user and/or group by hand.
 | 
					 | 
				
			||||||
   They're not created automatically.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. On the queues server, run the command scripts/startdaemons.sh.
 | 
					4. On the queues server, run the command scripts/startdaemons.sh.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,85 +444,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
 | 
					home-grown DB-based queue solution. This is strongly recommended for
 | 
				
			||||||
best response time, especially when using XMPP.
 | 
					best response time, especially when using XMPP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Themes
 | 
					After installation
 | 
				
			||||||
------
 | 
					==================
 | 
				
			||||||
 | 
					 | 
				
			||||||
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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Backups
 | 
					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
 | 
					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.
 | 
					and to backup the Web directory, try tar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Private
 | 
					Upgrading
 | 
				
			||||||
-------
 | 
					---------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The administrator can set the "private" flag for a site so that it's
 | 
					Upgrading is strongly recommended to stay up to date with security fixes
 | 
				
			||||||
not visible to non-logged-in users. (This is the default for new installs of version 1.0!)
 | 
					and new features. For instructions on how to upgrade GNU social code,
 | 
				
			||||||
 | 
					please see the UPGRADE file.
 | 
				
			||||||
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';
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@@ -1,5 +1,5 @@
 | 
				
			|||||||
# GNU social 1.1.3
 | 
					# GNU social 1.2.x
 | 
				
			||||||
February 2015-02-27
 | 
					2015
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(c) Free Software Foundation, Inc
 | 
					(c) Free Software Foundation, Inc
 | 
				
			||||||
(c) StatusNet, Inc
 | 
					(c) StatusNet, Inc
 | 
				
			||||||
@@ -100,15 +100,19 @@ for additional terms.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## New this version
 | 
					## New this version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is a security fix and bug fix release since 1.1.3-beta2.
 | 
					This is the development branch for the 1.2.x version of GNU social.
 | 
				
			||||||
All 1.1.x sites should upgrade to this version.
 | 
					All daring 1.1.x admins should upgrade to this version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
So far it includes the following changes:
 | 
					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/>)
 | 
					- 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>
 | 
					- Many improvements to ease adoption of the Qvitter front-end <https://github.com/hannesmannerheim/qvitter>
 | 
				
			||||||
- Protocol adaptions for improved performance and stability
 | 
					- 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:
 | 
					Upgrades from _StatusNet_ 1.1.1 will also experience these improvements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -146,7 +150,7 @@ In the current phase of development it is probably
 | 
				
			|||||||
recommended to use git as a means to stay up to date
 | 
					recommended to use git as a means to stay up to date
 | 
				
			||||||
with the source code. You can choose between these
 | 
					with the source code. You can choose between these
 | 
				
			||||||
branches:
 | 
					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
 | 
					- master    "testing", more updates, usually working well
 | 
				
			||||||
- nightly   "unstable", most updates, not always working
 | 
					- nightly   "unstable", most updates, not always working
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										143
									
								
								UPGRADE
									
									
									
									
									
								
							
							
						
						@@ -1,26 +1,77 @@
 | 
				
			|||||||
Upgrading
 | 
					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://bugz.foocorp.net/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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://bugz.foocorp.net/ (tag GNU social)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 
 | 
					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 
 | 
					1.1.1. If you are running a StatusNet version lower than this, please 
 | 
				
			||||||
follow the upgrade procedures for each respective StatusNet version.
 | 
					follow the upgrade procedures for each respective StatusNet version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You are now running StatusNet 1.1.1 and want to migrate to GNU social.
 | 
					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
 | 
					1.2.x. Beware there may be changes in minimum required version of PHP
 | 
				
			||||||
modules used, so double-check the INSTALL file's requirements list.
 | 
					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.
 | 
					directory structure and the database too. All tables. All data. Alles.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    0. Stop your queue daemons 'php scripts/stopdaemon.php' should do it.
 | 
					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. Stop your queue daemons 'bash scripts/stopdaemons.sh' should do it.
 | 
				
			||||||
    Not everyone runs queue daemons, but the above command won't hurt.
 | 
					    Not everyone runs queue daemons, but the above command won't hurt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    1. Unpack your GNU social code to a fresh directory.
 | 
					2. Unpack your GNU social code to a fresh directory. You can do this
 | 
				
			||||||
 | 
					    by cloning our git repository:
 | 
				
			||||||
 | 
					    $ git clone https://gitorious.org/social/mainline.git gnusocial
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    2. Synchronize your local files to the GNU social directory. These 
 | 
					3. Synchronize your local files to the GNU social directory. These 
 | 
				
			||||||
    will be the local files such as avatars, config and files:
 | 
					    will be the local files such as avatars, config and files:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        avatar/*
 | 
					        avatar/*
 | 
				
			||||||
@@ -30,70 +81,18 @@ directory structure and the database too. All tables. All data. Alles.
 | 
				
			|||||||
        .htaccess
 | 
					        .htaccess
 | 
				
			||||||
        config.php
 | 
					        config.php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    3. Replace your old StatusNet directory with the new GNU social
 | 
					    This command will point you in the right direction on how to do it:
 | 
				
			||||||
 | 
					    $ rsync -avP statusnet/{.htaccess,avatar,background,file,local,config.php} gnusocial/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4. Replace your old StatusNet directory with the new GNU social
 | 
				
			||||||
    directory in your webserver root.
 | 
					    directory in your webserver root.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    4. Run the upgrade script: 'php scripts/upgrade.php'
 | 
					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://bugz.foocorp.net/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    5. Start your queue daemons: 'php scripts/startdaemons.php'
 | 
					6. Start your queue daemons: 'bash scripts/startdaemons.sh'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    6. Report any issues at https://bugz.foocorp.net/ (tag GNU social)
 | 
					7. Report any issues at https://bugz.foocorp.net/ (tag GNU social)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Legacy StatusNet instructions
 | 
					 | 
				
			||||||
-----------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
These instructions are here for historical and perhaps informational
 | 
					 | 
				
			||||||
purposes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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.
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * StatusNet, the distributed open-source microblogging tool
 | 
					 * StatusNet, the distributed open-source microblogging tool
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -156,28 +155,23 @@ class ApiAccountRegisterAction extends ApiAction
 | 
				
			|||||||
            // annoy spammers
 | 
					            // annoy spammers
 | 
				
			||||||
            sleep(7);
 | 
					            sleep(7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    	if ($user = User::register(array('nickname' => $nickname,
 | 
					            try {
 | 
				
			||||||
 | 
					                $user = User::register(array('nickname' => $nickname,
 | 
				
			||||||
                                                    'password' => $password,
 | 
					                                                    'password' => $password,
 | 
				
			||||||
                                                    'email' => $email,
 | 
					                                                    'email' => $email,
 | 
				
			||||||
                                                    'fullname' => $fullname,
 | 
					                                                    'fullname' => $fullname,
 | 
				
			||||||
                                                    'homepage' => $homepage,
 | 
					                                                    'homepage' => $homepage,
 | 
				
			||||||
                                                    'bio' => $bio,
 | 
					                                                    'bio' => $bio,
 | 
				
			||||||
                                                    'location' => $location,
 | 
					                                                    'location' => $location,
 | 
				
			||||||
	                                                'code' => $this->code))) {
 | 
					                                                    '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));
 | 
					                Event::handle('EndRegistrationTry', array($this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $this->initDocument('json');
 | 
					                $this->initDocument('json');
 | 
				
			||||||
                $this->showJsonObjects($this->twitterUserArray($user->getProfile()));
 | 
					                $this->showJsonObjects($this->twitterUserArray($user->getProfile()));
 | 
				
			||||||
                $this->endDocument('json');
 | 
					                $this->endDocument('json');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	        } else {
 | 
					            } catch (Exception $e) {
 | 
				
			||||||
	            // TRANS: Form validation error displayed when trying to register with an invalid username or password.
 | 
					                $this->clientError($e->getMessage(), 400);
 | 
				
			||||||
	        	$this->clientError(_('Invalid username or password.'), 400);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allows the authenticating users to follow (subscribe) the user specified in
 | 
					 * 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);
 | 
					            $this->clientError(_('Could not follow user: profile not found.'), 403);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->user->isSubscribed($this->other)) {
 | 
					        if ($this->scoped->isSubscribed($this->other)) {
 | 
				
			||||||
            $errmsg = sprintf(
 | 
					            $errmsg = sprintf(
 | 
				
			||||||
                // TRANS: Client error displayed when trying to follow a user that's already being followed.
 | 
					                // 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.
 | 
					                // TRANS: %s is the nickname of the user that is already being followed.
 | 
				
			||||||
@@ -101,9 +99,9 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            Subscription::start($this->user->getProfile(), $this->other);
 | 
					            Subscription::start($this->scoped, $this->other);
 | 
				
			||||||
        } catch (Exception $e) {
 | 
					        } catch (AlreadyFulfilledException $e) {
 | 
				
			||||||
            $this->clientError($e->getMessage(), 403);
 | 
					            $this->clientError($e->getMessage(), 409);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->initDocument($this->format);
 | 
					        $this->initDocument($this->format);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allows the authenticating users to unfollow (unsubscribe) the user specified in
 | 
					 * Allows the authenticating users to unfollow (unsubscribe) the user specified in
 | 
				
			||||||
@@ -48,7 +46,9 @@ if (!defined('STATUSNET')) {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
class ApiFriendshipsDestroyAction extends ApiAuthAction
 | 
					class ApiFriendshipsDestroyAction extends ApiAuthAction
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    var $other  = null;
 | 
					    protected $needPost = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $other = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Take arguments for running
 | 
					     * Take arguments for running
 | 
				
			||||||
@@ -58,11 +58,10 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
 | 
				
			|||||||
     * @return boolean success flag
 | 
					     * @return boolean success flag
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function prepare($args)
 | 
					    protected function prepare(array $args=array())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					        parent::prepare($args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->user   = $this->auth_user;
 | 
					 | 
				
			||||||
        $this->other = $this->getTargetProfile($this->arg('id'));
 | 
					        $this->other = $this->getTargetProfile($this->arg('id'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
@@ -73,58 +72,40 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * Check the format and show the user info
 | 
					     * Check the format and show the user info
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param array $args $_REQUEST data (unused)
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function handle($args)
 | 
					    protected function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handle($args);
 | 
					        parent::handle();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!in_array($this->format, array('xml', 'json'))) {
 | 
					        if (!in_array($this->format, array('xml', 'json'))) {
 | 
				
			||||||
            $this->clientError(
 | 
					            $this->clientError(
 | 
				
			||||||
                // TRANS: Client error displayed when coming across a non-supported API method.
 | 
					                // TRANS: Client error displayed when coming across a non-supported API method.
 | 
				
			||||||
                _('API method not found.'),
 | 
					                _('API method not found.'),
 | 
				
			||||||
                404,
 | 
					                404
 | 
				
			||||||
                $this->format
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (empty($this->other)) {
 | 
					        if (!$this->other instanceof Profile) {
 | 
				
			||||||
            $this->clientError(
 | 
					            $this->clientError(
 | 
				
			||||||
                // TRANS: Client error displayed when trying to unfollow a user that cannot be found.
 | 
					                // TRANS: Client error displayed when trying to unfollow a user that cannot be found.
 | 
				
			||||||
                _('Could not unfollow user: User not found.'),
 | 
					                _('Could not unfollow user: User not found.'),
 | 
				
			||||||
                403,
 | 
					                403
 | 
				
			||||||
                $this->format
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Don't allow unsubscribing from yourself!
 | 
					        // Don't allow unsubscribing from yourself!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->user->id == $this->other->id) {
 | 
					        if ($this->scoped->id == $this->other->id) {
 | 
				
			||||||
            $this->clientError(
 | 
					            $this->clientError(
 | 
				
			||||||
                // TRANS: Client error displayed when trying to unfollow self.
 | 
					                // TRANS: Client error displayed when trying to unfollow self.
 | 
				
			||||||
                _("You cannot unfollow yourself."),
 | 
					                _("You cannot unfollow yourself."),
 | 
				
			||||||
                403,
 | 
					                403
 | 
				
			||||||
                $this->format
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // throws an exception on error
 | 
					        // throws an exception on error
 | 
				
			||||||
        Subscription::cancel($this->user->getProfile(), $this->other);
 | 
					        Subscription::cancel($this->scoped, $this->other);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->initDocument($this->format);
 | 
					        $this->initDocument($this->format);
 | 
				
			||||||
        $this->showProfile($this->other, $this->format);
 | 
					        $this->showProfile($this->other, $this->format);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Tests for the existence of friendship between two users. Will return true if
 | 
					 * 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
 | 
					     * @return boolean success flag
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function prepare($args)
 | 
					    protected function prepare(array $args=array())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					        parent::prepare($args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,22 +70,18 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * Check the format and show the user info
 | 
					     * Check the format and show the user info
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param array $args $_REQUEST data (unused)
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function handle($args)
 | 
					    protected function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handle($args);
 | 
					        parent::handle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (empty($this->profile_a) || empty($this->profile_b)) {
 | 
					        if (empty($this->profile_a) || empty($this->profile_b)) {
 | 
				
			||||||
            $this->clientError(
 | 
					            $this->clientError(
 | 
				
			||||||
                // TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists.
 | 
					                // 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.'),
 | 
					                _('Two valid IDs or nick names must be supplied.'),
 | 
				
			||||||
                400,
 | 
					                400
 | 
				
			||||||
                $this->format
 | 
					 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $result = Subscription::exists($this->profile_a, $this->profile_b);
 | 
					        $result = Subscription::exists($this->profile_a, $this->profile_b);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Outputs detailed information about the relationship between two users
 | 
					 * Outputs detailed information about the relationship between two users
 | 
				
			||||||
@@ -56,7 +54,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return boolean success flag
 | 
					     * @return boolean success flag
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function prepare($args)
 | 
					    protected function prepare(array $args=array())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					        parent::prepare($args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,13 +107,11 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * Check the format and show the user info
 | 
					     * Check the format and show the user info
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param array $args $_REQUEST data (unused)
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function handle($args)
 | 
					    protected function handle()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handle($args);
 | 
					        parent::handle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!in_array($this->format, array('xml', 'json'))) {
 | 
					        if (!in_array($this->format, array('xml', 'json'))) {
 | 
				
			||||||
            // TRANS: Client error displayed when coming across a non-supported API method.
 | 
					            // TRANS: Client error displayed when coming across a non-supported API method.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,10 @@ class ApiTimelineUserAction extends ApiBareAuthAction
 | 
				
			|||||||
            $this->clientError(_('No such user.'), 404);
 | 
					            $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();
 | 
					        $this->notices = $this->getNotices();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
@@ -405,7 +409,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Get (safe!) HTML and text versions of the content
 | 
					        // Get (safe!) HTML and text versions of the content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rendered = $this->purify($sourceContent);
 | 
					        $rendered = common_purify($sourceContent);
 | 
				
			||||||
        $content = common_strip_html($rendered);
 | 
					        $content = common_strip_html($rendered);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $shortened = $this->auth_user->shortenLinks($content);
 | 
					        $shortened = $this->auth_user->shortenLinks($content);
 | 
				
			||||||
@@ -504,13 +508,4 @@ class ApiTimelineUserAction extends ApiBareAuthAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return $saved;
 | 
					        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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -230,18 +230,11 @@ class AtompubsubscriptionfeedAction extends AtompubAction
 | 
				
			|||||||
                $this->clientError(sprintf(_('Unknown profile %s.'), $person->id));
 | 
					                $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
 | 
					                // 409 Conflict
 | 
				
			||||||
                // TRANS: Client error displayed trying to subscribe to an already subscribed profile.
 | 
					                $this->clientError($e->getMessage(), 409);
 | 
				
			||||||
                // 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));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Event::handle('EndAtomPubNewActivity', array($activity, $sub));
 | 
					            Event::handle('EndAtomPubNewActivity', array($activity, $sub));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,6 @@ class Attachment_thumbnailAction extends AttachmentAction
 | 
				
			|||||||
            common_redirect($e->file->getUrl());
 | 
					            common_redirect($e->file->getUrl());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        common_redirect($thumbnail->getUrl());
 | 
					        common_redirect(File_thumbnail::url($thumbnail->filename));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,13 +28,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
define('MAX_ORIGINAL', 480);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Upload an avatar
 | 
					 * Upload an avatar
 | 
				
			||||||
@@ -369,13 +363,27 @@ class AvatarsettingsAction extends SettingsAction
 | 
				
			|||||||
        $dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):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_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;
 | 
					        $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')));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $box = array('width' => $size, 'height' => $size,
 | 
				
			||||||
 | 
					                     'x' => $dest_x,   'y' => $dest_y,
 | 
				
			||||||
 | 
					                     'w' => $dest_w,   'h' => $dest_h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $user = common_current_user();
 | 
					        $user = common_current_user();
 | 
				
			||||||
        $profile = $user->getProfile();
 | 
					        $profile = $user->getProfile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $imagefile = new ImageFile($user->id, $filedata['filepath']);
 | 
					        $imagefile = new ImageFile(null, $filedata['filepath']);
 | 
				
			||||||
        $filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);
 | 
					        $filename = Avatar::filename($profile->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 ($profile->setOriginal($filename)) {
 | 
				
			||||||
            @unlink($filedata['filepath']);
 | 
					            @unlink($filedata['filepath']);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,23 +43,17 @@ class CancelsubscriptionAction extends FormAction
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    protected $needPost = true;
 | 
					    protected $needPost = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function prepare(array $args=array())
 | 
					    protected function doPreparation()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $profile_id = $this->int('unsubscribeto');
 | 
					        $profile_id = $this->int('unsubscribeto');
 | 
				
			||||||
        $this->target = Profile::getKV('id', $profile_id);
 | 
					        $this->target = Profile::getKV('id', $profile_id);
 | 
				
			||||||
        if (!$this->target instanceof Profile) {
 | 
					        if (!$this->target instanceof Profile) {
 | 
				
			||||||
            throw new NoProfileException($profile_id);
 | 
					            throw new NoProfileException($profile_id);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function handlePost()
 | 
					    protected function doPost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handlePost();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            $request = Subscription_queue::pkeyGet(array('subscriber' => $this->scoped->id,
 | 
					            $request = Subscription_queue::pkeyGet(array('subscriber' => $this->scoped->id,
 | 
				
			||||||
                                                         'subscribed' => $this->target->id));
 | 
					                                                         'subscribed' => $this->target->id));
 | 
				
			||||||
@@ -70,7 +64,7 @@ class CancelsubscriptionAction extends FormAction
 | 
				
			|||||||
            common_debug('Tried to cancel a non-existing pending subscription');
 | 
					            common_debug('Tried to cancel a non-existing pending subscription');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (StatusNet::isAjax()) {
 | 
					        if (GNUsocial::isAjax()) {
 | 
				
			||||||
            $this->startHTML('text/xml;charset=utf-8');
 | 
					            $this->startHTML('text/xml;charset=utf-8');
 | 
				
			||||||
            $this->elementStart('head');
 | 
					            $this->elementStart('head');
 | 
				
			||||||
            // TRANS: Title after unsubscribing from a group.
 | 
					            // TRANS: Title after unsubscribing from a group.
 | 
				
			||||||
@@ -82,10 +76,7 @@ class CancelsubscriptionAction extends FormAction
 | 
				
			|||||||
            $this->elementEnd('body');
 | 
					            $this->elementEnd('body');
 | 
				
			||||||
            $this->endHTML();
 | 
					            $this->endHTML();
 | 
				
			||||||
            exit();
 | 
					            exit();
 | 
				
			||||||
        } else {
 | 
					        }
 | 
				
			||||||
            common_redirect(common_local_url('subscriptions',
 | 
					        common_redirect(common_local_url('subscriptions', array('nickname' => $this->scoped->getNickname())), 303);
 | 
				
			||||||
                                             array('nickname' => $this->scoped->nickname)),
 | 
					 | 
				
			||||||
                            303);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,11 +174,15 @@ class DocNav extends Menu
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    function show()
 | 
					    function show()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (Event::handle('StartDocNav', array($this))) {
 | 
				
			||||||
            $stub = new HomeStubNav($this->action);
 | 
					            $stub = new HomeStubNav($this->action);
 | 
				
			||||||
            $this->submenu(_m('MENU','Home'), $stub);
 | 
					            $this->submenu(_m('MENU','Home'), $stub);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $docs = new DocListNav($this->action);
 | 
					            $docs = new DocListNav($this->action);
 | 
				
			||||||
            $this->submenu(_m('MENU','Docs'), $docs);
 | 
					            $this->submenu(_m('MENU','Docs'), $docs);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Event::handle('EndDocNav', array($this));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,7 +91,7 @@ class EmailsettingsAction extends SettingsAction
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    function showContent()
 | 
					    function showContent()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $user = common_current_user();
 | 
					        $user = $this->scoped->getUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->elementStart('form', array('method' => 'post',
 | 
					        $this->elementStart('form', array('method' => 'post',
 | 
				
			||||||
                                          'id' => 'form_settings_email',
 | 
					                                          'id' => 'form_settings_email',
 | 
				
			||||||
@@ -313,17 +313,15 @@ class EmailsettingsAction extends SettingsAction
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    function savePreferences()
 | 
					    function savePreferences()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $user = common_current_user();
 | 
					        $user = $this->scoped->getUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
 | 
					        if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
 | 
				
			||||||
            $emailnotifysub   = $this->boolean('emailnotifysub');
 | 
					            $emailnotifysub   = $this->booleanintstring('emailnotifysub');
 | 
				
			||||||
            $emailnotifymsg   = $this->boolean('emailnotifymsg');
 | 
					            $emailnotifymsg   = $this->booleanintstring('emailnotifymsg');
 | 
				
			||||||
            $emailnotifynudge = $this->boolean('emailnotifynudge');
 | 
					            $emailnotifynudge = $this->booleanintstring('emailnotifynudge');
 | 
				
			||||||
            $emailnotifyattn  = $this->boolean('emailnotifyattn');
 | 
					            $emailnotifyattn  = $this->booleanintstring('emailnotifyattn');
 | 
				
			||||||
            $emailmicroid     = $this->boolean('emailmicroid');
 | 
					            $emailmicroid     = $this->booleanintstring('emailmicroid');
 | 
				
			||||||
            $emailpost        = $this->boolean('emailpost');
 | 
					            $emailpost        = $this->booleanintstring('emailpost');
 | 
				
			||||||
 | 
					 | 
				
			||||||
            assert(!is_null($user)); // should already be checked
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->query('BEGIN');
 | 
					            $user->query('BEGIN');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -340,6 +338,7 @@ class EmailsettingsAction extends SettingsAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if ($result === false) {
 | 
					            if ($result === false) {
 | 
				
			||||||
                common_log_db_error($user, 'UPDATE', __FILE__);
 | 
					                common_log_db_error($user, 'UPDATE', __FILE__);
 | 
				
			||||||
 | 
					                $user->query('ROLLBACK');
 | 
				
			||||||
                // TRANS: Server error thrown on database error updating e-mail preferences.
 | 
					                // TRANS: Server error thrown on database error updating e-mail preferences.
 | 
				
			||||||
                $this->serverError(_('Could not update user.'));
 | 
					                $this->serverError(_('Could not update user.'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,13 +28,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
define('MAX_ORIGINAL', 480);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Upload an avatar
 | 
					 * 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_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_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'];
 | 
					        $dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$filedata['height'];
 | 
				
			||||||
        $size = min($dest_w, $dest_h);
 | 
					        $size = min($dest_w, $dest_h, common_config('avatar', 'maxsize'));
 | 
				
			||||||
        $size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size;
 | 
					        $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']);
 | 
					        $profile = $this->group->getProfile();
 | 
				
			||||||
        $filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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']);
 | 
					            @unlink($filedata['filepath']);
 | 
				
			||||||
            unset($_SESSION['FILEDATA']);
 | 
					            unset($_SESSION['FILEDATA']);
 | 
				
			||||||
            $this->mode = 'upload';
 | 
					            $this->mode = 'upload';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,7 +118,7 @@ class InviteAction extends Action
 | 
				
			|||||||
                        $this->already[] = $other;
 | 
					                        $this->already[] = $other;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        try {
 | 
					                        try {
 | 
				
			||||||
                            Subscription::start($profile, $other);
 | 
					                            Subscription::ensureStart($profile, $other);
 | 
				
			||||||
                            $this->subbed[] = $other;
 | 
					                            $this->subbed[] = $other;
 | 
				
			||||||
                        } catch (Exception $e) {
 | 
					                        } catch (Exception $e) {
 | 
				
			||||||
                            // subscription failed, but keep working
 | 
					                            // subscription failed, but keep working
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,24 +36,6 @@ class LoginAction extends FormAction
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    protected $needLogin = false;
 | 
					    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
 | 
					     * Handle input, produce output
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -79,10 +61,8 @@ class LoginAction extends FormAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function handlePost()
 | 
					    protected function doPost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handlePost();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // XXX: login throttle
 | 
					        // XXX: login throttle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nickname = $this->trimmed('nickname');
 | 
					        $nickname = $this->trimmed('nickname');
 | 
				
			||||||
@@ -122,22 +102,6 @@ class LoginAction extends FormAction
 | 
				
			|||||||
        common_redirect($url, 303);
 | 
					        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()
 | 
					    function showScripts()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::showScripts();
 | 
					        parent::showScripts();
 | 
				
			||||||
@@ -208,7 +172,7 @@ class LoginAction extends FormAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function getInstructions()
 | 
					    protected function getInstructions()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (common_logged_in() && !common_is_real_login() &&
 | 
					        if (common_logged_in() && !common_is_real_login() &&
 | 
				
			||||||
            common_get_returnto()) {
 | 
					            common_get_returnto()) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,9 +28,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add a new application
 | 
					 * Add a new application
 | 
				
			||||||
@@ -51,10 +49,8 @@ class NewApplicationAction extends FormAction
 | 
				
			|||||||
        return _('New application');
 | 
					        return _('New application');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function handlePost()
 | 
					    protected function doPost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handlePost();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->arg('cancel')) {
 | 
					        if ($this->arg('cancel')) {
 | 
				
			||||||
            common_redirect(common_local_url('oauthappssettings'), 303);
 | 
					            common_redirect(common_local_url('oauthappssettings'), 303);
 | 
				
			||||||
        } elseif ($this->arg('save')) {
 | 
					        } elseif ($this->arg('save')) {
 | 
				
			||||||
@@ -65,27 +61,15 @@ class NewApplicationAction extends FormAction
 | 
				
			|||||||
        $this->clientError(_('Unexpected form submission.'));
 | 
					        $this->clientError(_('Unexpected form submission.'));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showForm($msg=null)
 | 
					    protected function getForm()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->msg = $msg;
 | 
					        return new ApplicationEditForm($this);
 | 
				
			||||||
        $this->showPage();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showContent()
 | 
					    protected function getInstructions()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $form = new ApplicationEditForm($this);
 | 
					 | 
				
			||||||
        $form->show();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function showPageNotice()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->msg) {
 | 
					 | 
				
			||||||
            $this->element('p', 'error', $this->msg);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $this->element('p', 'instructions',
 | 
					 | 
				
			||||||
        // TRANS: Form instructions for registering a new application.
 | 
					        // TRANS: Form instructions for registering a new application.
 | 
				
			||||||
                           _('Use this form to register a new application.'));
 | 
					        return _('Use this form to register a new application.');
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function trySave()
 | 
					    private function trySave()
 | 
				
			||||||
@@ -181,6 +165,7 @@ class NewApplicationAction extends FormAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (!$result) {
 | 
					        if (!$result) {
 | 
				
			||||||
            common_log_db_error($consumer, 'INSERT', __FILE__);
 | 
					            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.
 | 
					            // 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.'));
 | 
					            $this->serverError(_('Could not create application.'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -191,9 +176,9 @@ class NewApplicationAction extends FormAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (!$this->app_id) {
 | 
					        if (!$this->app_id) {
 | 
				
			||||||
            common_log_db_error($app, 'INSERT', __FILE__);
 | 
					            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.
 | 
					            // 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.'));
 | 
					            $this->serverError(_('Could not create application.'));
 | 
				
			||||||
            $app->query('ROLLBACK');
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add a new group
 | 
					 * Add a new group
 | 
				
			||||||
@@ -48,6 +46,8 @@ class NewgroupAction extends FormAction
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    protected $group;
 | 
					    protected $group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected $form = 'GroupEdit';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function getGroup() {
 | 
					    function getGroup() {
 | 
				
			||||||
        return $this->group;
 | 
					        return $this->group;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -58,39 +58,23 @@ class NewgroupAction extends FormAction
 | 
				
			|||||||
        return _('New group');
 | 
					        return _('New group');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    protected function doPreparation()
 | 
				
			||||||
     * Prepare to run
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected function prepare(array $args=array())
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // $this->scoped is the current user profile
 | 
					        // $this->scoped is the current user profile
 | 
				
			||||||
        if (!$this->scoped->hasRight(Right::CREATEGROUP)) {
 | 
					        if (!$this->scoped->hasRight(Right::CREATEGROUP)) {
 | 
				
			||||||
            // TRANS: Client exception thrown when a user tries to create a group while banned.
 | 
					            // 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);
 | 
					            $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();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function showInstructions()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->element('p', 'instructions',
 | 
					 | 
				
			||||||
        // TRANS: Form instructions for group create form.
 | 
					        // TRANS: Form instructions for group create form.
 | 
				
			||||||
                       _('Use this form to create a new group.'));
 | 
					        return _('Use this form to create a new group.');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function handlePost()
 | 
					    protected function doPost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handlePost();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (Event::handle('StartGroupSaveForm', array($this))) {
 | 
					        if (Event::handle('StartGroupSaveForm', array($this))) {
 | 
				
			||||||
            $nickname = Nickname::normalize($this->trimmed('newnickname'), true);
 | 
					            $nickname = Nickname::normalize($this->trimmed('newnickname'), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,7 +117,6 @@ class NewgroupAction extends FormAction
 | 
				
			|||||||
                                           'Too many aliases! Maximum %d allowed.',
 | 
					                                           'Too many aliases! Maximum %d allowed.',
 | 
				
			||||||
                                           common_config('group', 'maxaliases')),
 | 
					                                           common_config('group', 'maxaliases')),
 | 
				
			||||||
                                        common_config('group', 'maxaliases')));
 | 
					                                        common_config('group', 'maxaliases')));
 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($private) {
 | 
					            if ($private) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,9 +30,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Action for posting new notices
 | 
					 * Action for posting new notices
 | 
				
			||||||
@@ -62,6 +60,9 @@ class NewnoticeAction extends FormAction
 | 
				
			|||||||
            // TRANS: Page title after sending a notice.
 | 
					            // TRANS: Page title after sending a notice.
 | 
				
			||||||
            return _('Notice posted');
 | 
					            return _('Notice posted');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if ($this->int('inreplyto')) {
 | 
				
			||||||
 | 
					            return _m('TITLE', 'New reply');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        // TRANS: Page title for sending a new notice.
 | 
					        // TRANS: Page title for sending a new notice.
 | 
				
			||||||
        return _m('TITLE','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 successful, will show the notice, or return an Ajax-y result.
 | 
				
			||||||
     * If not, it will show an error message -- possibly Ajax-y.
 | 
					     * If not, it will show an error message -- possibly Ajax-y.
 | 
				
			||||||
@@ -90,17 +91,15 @@ class NewnoticeAction extends FormAction
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return void
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function handlePost()
 | 
					    protected function doPost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::handlePost();
 | 
					        assert($this->scoped instanceof Profile); // XXX: maybe an error instead...
 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert($this->scoped); // XXX: maybe an error instead...
 | 
					 | 
				
			||||||
        $user = $this->scoped->getUser();
 | 
					        $user = $this->scoped->getUser();
 | 
				
			||||||
        $content = $this->trimmed('status_textarea');
 | 
					        $content = $this->trimmed('status_textarea');
 | 
				
			||||||
        $options = array();
 | 
					        $options = array();
 | 
				
			||||||
        Event::handle('StartSaveNewNoticeWeb', array($this, $user, &$content, &$options));
 | 
					        Event::handle('StartSaveNewNoticeWeb', array($this, $user, &$content, &$options));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!$content) {
 | 
					        if (empty($content)) {
 | 
				
			||||||
            // TRANS: Client error displayed trying to send a notice without content.
 | 
					            // TRANS: Client error displayed trying to send a notice without content.
 | 
				
			||||||
            $this->clientError(_('No content!'));
 | 
					            $this->clientError(_('No content!'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -110,7 +109,7 @@ class NewnoticeAction extends FormAction
 | 
				
			|||||||
        $cmd = $inter->handle_command($user, $content);
 | 
					        $cmd = $inter->handle_command($user, $content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($cmd) {
 | 
					        if ($cmd) {
 | 
				
			||||||
            if (StatusNet::isAjax()) {
 | 
					            if (GNUsocial::isAjax()) {
 | 
				
			||||||
                $cmd->execute(new AjaxWebChannel($this));
 | 
					                $cmd->execute(new AjaxWebChannel($this));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $cmd->execute(new WebChannel($this));
 | 
					                $cmd->execute(new WebChannel($this));
 | 
				
			||||||
@@ -128,7 +127,7 @@ class NewnoticeAction extends FormAction
 | 
				
			|||||||
                                       Notice::maxContent()));
 | 
					                                       Notice::maxContent()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $replyto = intval($this->trimmed('inreplyto'));
 | 
					        $replyto = $this->int('inreplyto');
 | 
				
			||||||
        if ($replyto) {
 | 
					        if ($replyto) {
 | 
				
			||||||
            $options['reply_to'] = $replyto;
 | 
					            $options['reply_to'] = $replyto;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -195,7 +194,7 @@ class NewnoticeAction extends FormAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options));
 | 
					        Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!StatusNet::isAjax()) {
 | 
					        if (!GNUsocial::isAjax()) {
 | 
				
			||||||
            $url = common_local_url('shownotice', array('notice' => $this->stored->id));
 | 
					            $url = common_local_url('shownotice', array('notice' => $this->stored->id));
 | 
				
			||||||
            common_redirect($url, 303);
 | 
					            common_redirect($url, 303);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,8 +82,8 @@ class ProfilesettingsAction extends SettingsAction
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    function showContent()
 | 
					    function showContent()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $user = common_current_user();
 | 
					        $profile = $this->scoped;
 | 
				
			||||||
        $profile = $user->getProfile();
 | 
					        $user = $this->scoped->getUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->elementStart('form', array('method' => 'post',
 | 
					        $this->elementStart('form', array('method' => 'post',
 | 
				
			||||||
                                          'id' => 'form_settings_profile',
 | 
					                                          'id' => 'form_settings_profile',
 | 
				
			||||||
@@ -104,7 +104,9 @@ class ProfilesettingsAction extends SettingsAction
 | 
				
			|||||||
                         // TRANS: Tooltip for field label in form for profile settings.
 | 
					                         // TRANS: Tooltip for field label in form for profile settings.
 | 
				
			||||||
                         _('1-64 lowercase letters or numbers, no punctuation or spaces.'),
 | 
					                         _('1-64 lowercase letters or numbers, no punctuation or spaces.'),
 | 
				
			||||||
                         null, false,   // "name" (will be set to id), then "required"
 | 
					                         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->elementEnd('li');
 | 
				
			||||||
            $this->elementStart('li');
 | 
					            $this->elementStart('li');
 | 
				
			||||||
            // TRANS: Field label in form for profile settings.
 | 
					            // TRANS: Field label in form for profile settings.
 | 
				
			||||||
@@ -260,9 +262,9 @@ class ProfilesettingsAction extends SettingsAction
 | 
				
			|||||||
            $homepage = $this->trimmed('homepage');
 | 
					            $homepage = $this->trimmed('homepage');
 | 
				
			||||||
            $bio = $this->trimmed('bio');
 | 
					            $bio = $this->trimmed('bio');
 | 
				
			||||||
            $location = $this->trimmed('location');
 | 
					            $location = $this->trimmed('location');
 | 
				
			||||||
            $autosubscribe = $this->boolean('autosubscribe');
 | 
					            $autosubscribe = $this->booleanintstring('autosubscribe');
 | 
				
			||||||
            $subscribe_policy = $this->trimmed('subscribe_policy');
 | 
					            $subscribe_policy = $this->trimmed('subscribe_policy');
 | 
				
			||||||
            $private_stream = $this->boolean('private_stream');
 | 
					            $private_stream = $this->booleanintstring('private_stream');
 | 
				
			||||||
            $language = $this->trimmed('language');
 | 
					            $language = $this->trimmed('language');
 | 
				
			||||||
            $timezone = $this->trimmed('timezone');
 | 
					            $timezone = $this->trimmed('timezone');
 | 
				
			||||||
            $tagstring = $this->trimmed('tags');
 | 
					            $tagstring = $this->trimmed('tags');
 | 
				
			||||||
@@ -398,7 +400,7 @@ class ProfilesettingsAction extends SettingsAction
 | 
				
			|||||||
                    $orig = clone($prefs);
 | 
					                    $orig = clone($prefs);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $prefs->share_location = $this->boolean('sharelocation');
 | 
					                $prefs->share_location = $this->booleanintstring('sharelocation');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ($exists) {
 | 
					                if ($exists) {
 | 
				
			||||||
                    $result = $prefs->update($orig);
 | 
					                    $result = $prefs->update($orig);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,9 +27,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
 | 
					if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * An action for registering a new user account
 | 
					 * An action for registering a new user account
 | 
				
			||||||
@@ -229,19 +227,16 @@ class RegisterAction extends Action
 | 
				
			|||||||
            } else if ($password != $confirm) {
 | 
					            } else if ($password != $confirm) {
 | 
				
			||||||
                // TRANS: Form validation error displayed when trying to register with non-matching passwords.
 | 
					                // TRANS: Form validation error displayed when trying to register with non-matching passwords.
 | 
				
			||||||
                $this->showForm(_('Passwords do not match.'));
 | 
					                $this->showForm(_('Passwords do not match.'));
 | 
				
			||||||
            } else if ($user = User::register(array('nickname' => $nickname,
 | 
					            } else {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    $user = User::register(array('nickname' => $nickname,
 | 
				
			||||||
                                                    'password' => $password,
 | 
					                                                    'password' => $password,
 | 
				
			||||||
                                                    'email' => $email,
 | 
					                                                    'email' => $email,
 | 
				
			||||||
                                                    'fullname' => $fullname,
 | 
					                                                    'fullname' => $fullname,
 | 
				
			||||||
                                                    'homepage' => $homepage,
 | 
					                                                    'homepage' => $homepage,
 | 
				
			||||||
                                                    'bio' => $bio,
 | 
					                                                    'bio' => $bio,
 | 
				
			||||||
                                                    'location' => $location,
 | 
					                                                    'location' => $location,
 | 
				
			||||||
                                                    'code' => $code))) {
 | 
					                                                    'code' => $code));
 | 
				
			||||||
                if (!($user instanceof User)) {
 | 
					 | 
				
			||||||
                    // TRANS: Form validation error displayed when trying to register with an invalid username or password.
 | 
					 | 
				
			||||||
                    $this->showForm(_('Invalid username or password.'));
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                    // success!
 | 
					                    // success!
 | 
				
			||||||
                    if (!common_set_user($user)) {
 | 
					                    if (!common_set_user($user)) {
 | 
				
			||||||
                        // TRANS: Server error displayed when saving fails during user registration.
 | 
					                        // TRANS: Server error displayed when saving fails during user registration.
 | 
				
			||||||
@@ -260,9 +255,10 @@ class RegisterAction extends Action
 | 
				
			|||||||
                    Event::handle('EndRegistrationTry', array($this));
 | 
					                    Event::handle('EndRegistrationTry', array($this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $this->showSuccess();
 | 
					                    $this->showSuccess();
 | 
				
			||||||
            } else {
 | 
					                } catch (Exception $e) {
 | 
				
			||||||
                    // TRANS: Form validation error displayed when trying to register with an invalid username or password.
 | 
					                    // TRANS: Form validation error displayed when trying to register with an invalid username or password.
 | 
				
			||||||
                $this->showForm(_('Invalid username or password.'));
 | 
					                    $this->showForm($e->getMessage());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,13 +27,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require_once INSTALLDIR.'/lib/personalgroupnav.php';
 | 
					 | 
				
			||||||
require_once INSTALLDIR.'/lib/noticelist.php';
 | 
					 | 
				
			||||||
require_once INSTALLDIR.'/lib/feedlist.php';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * List of replies
 | 
					 * List of replies
 | 
				
			||||||
@@ -44,47 +38,34 @@ 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
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 * @link     http://status.net/
 | 
					 * @link     http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class RepliesAction extends Action
 | 
					class RepliesAction extends ManagedAction
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    var $page = null;
 | 
					    var $page = null;
 | 
				
			||||||
    var $notice;
 | 
					    var $notice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    protected function doPreparation()
 | 
				
			||||||
     * 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)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $nickname = common_canonical_nickname($this->arg('nickname'));
 | 
					        $nickname = common_canonical_nickname($this->arg('nickname'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->user = User::getKV('nickname', $nickname);
 | 
					        $this->user = User::getKV('nickname', $nickname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!$this->user) {
 | 
					        if (!$this->user instanceof User) {
 | 
				
			||||||
            // TRANS: Client error displayed when trying to reply to a non-exsting user.
 | 
					            // TRANS: Client error displayed when trying to reply to a non-exsting user.
 | 
				
			||||||
            $this->clientError(_('No such user.'));
 | 
					            $this->clientError(_('No such user.'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $profile = $this->user->getProfile();
 | 
					        $this->target = $this->user->getProfile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!$profile) {
 | 
					        if (!$this->target instanceof Profile) {
 | 
				
			||||||
            // TRANS: Error message displayed when referring to a user without a profile.
 | 
					            // TRANS: Error message displayed when referring to a user without a profile.
 | 
				
			||||||
            $this->serverError(_('User has no profile.'));
 | 
					            $this->serverError(_('User has no profile.'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
 | 
					        $this->page = $this->int('page') ?: 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        common_set_returnto($this->selfUrl());
 | 
					        common_set_returnto($this->selfUrl());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $stream = new ReplyNoticeStream($this->user->id,
 | 
					        $stream = new ReplyNoticeStream($this->target->getID(), $this->scoped);
 | 
				
			||||||
                                        Profile::current());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE,
 | 
					        $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE,
 | 
				
			||||||
                                            NOTICES_PER_PAGE + 1);
 | 
					                                            NOTICES_PER_PAGE + 1);
 | 
				
			||||||
@@ -93,23 +74,6 @@ class RepliesAction extends Action
 | 
				
			|||||||
            // TRANS: Client error when page not found (404)
 | 
					            // TRANS: Client error when page not found (404)
 | 
				
			||||||
            $this->clientError(_('No such page.'), 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();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -124,12 +88,12 @@ class RepliesAction extends Action
 | 
				
			|||||||
        if ($this->page == 1) {
 | 
					        if ($this->page == 1) {
 | 
				
			||||||
            // TRANS: Title for first page of replies for a user.
 | 
					            // TRANS: Title for first page of replies for a user.
 | 
				
			||||||
            // TRANS: %s is a user nickname.
 | 
					            // TRANS: %s is a user nickname.
 | 
				
			||||||
            return sprintf(_("Replies to %s"), $this->user->nickname);
 | 
					            return sprintf(_("Replies to %s"), $this->target->getNickname());
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // TRANS: Title for all but the first page of replies for a user.
 | 
					            // 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.
 | 
					            // TRANS: %1$s is a user nickname, %2$d is a page number.
 | 
				
			||||||
            return sprintf(_('Replies to %1$s, page %2$d'),
 | 
					            return sprintf(_('Replies to %1$s, page %2$d'),
 | 
				
			||||||
                           $this->user->nickname,
 | 
					                           $this->target->getNickname(),
 | 
				
			||||||
                           $this->page);
 | 
					                           $this->page);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -144,7 +108,7 @@ class RepliesAction extends Action
 | 
				
			|||||||
        return array(new Feed(Feed::JSON,
 | 
					        return array(new Feed(Feed::JSON,
 | 
				
			||||||
                              common_local_url('ApiTimelineMentions',
 | 
					                              common_local_url('ApiTimelineMentions',
 | 
				
			||||||
                                               array(
 | 
					                                               array(
 | 
				
			||||||
                                                    'id' => $this->user->nickname,
 | 
					                                                    'id' => $this->target->getNickname(),
 | 
				
			||||||
                                                    'format' => 'as')),
 | 
					                                                    'format' => 'as')),
 | 
				
			||||||
                              // TRANS: Link for feed with replies for a user.
 | 
					                              // TRANS: Link for feed with replies for a user.
 | 
				
			||||||
                              // TRANS: %s is a user nickname.
 | 
					                              // TRANS: %s is a user nickname.
 | 
				
			||||||
@@ -152,38 +116,31 @@ class RepliesAction extends Action
 | 
				
			|||||||
                                      $this->user->nickname)),
 | 
					                                      $this->user->nickname)),
 | 
				
			||||||
                     new Feed(Feed::RSS1,
 | 
					                     new Feed(Feed::RSS1,
 | 
				
			||||||
                              common_local_url('repliesrss',
 | 
					                              common_local_url('repliesrss',
 | 
				
			||||||
                                               array('nickname' => $this->user->nickname)),
 | 
					                                               array('nickname' => $this->target->getNickname())),
 | 
				
			||||||
                              // TRANS: Link for feed with replies for a user.
 | 
					                              // TRANS: Link for feed with replies for a user.
 | 
				
			||||||
                              // TRANS: %s is a user nickname.
 | 
					                              // TRANS: %s is a user nickname.
 | 
				
			||||||
                              sprintf(_('Replies feed for %s (RSS 1.0)'),
 | 
					                              sprintf(_('Replies feed for %s (RSS 1.0)'),
 | 
				
			||||||
                                      $this->user->nickname)),
 | 
					                                      $this->target->getNickname())),
 | 
				
			||||||
                     new Feed(Feed::RSS2,
 | 
					                     new Feed(Feed::RSS2,
 | 
				
			||||||
                              common_local_url('ApiTimelineMentions',
 | 
					                              common_local_url('ApiTimelineMentions',
 | 
				
			||||||
                                               array(
 | 
					                                               array(
 | 
				
			||||||
                                                    'id' => $this->user->nickname,
 | 
					                                                    'id' => $this->target->getNickname(),
 | 
				
			||||||
                                                    'format' => 'rss')),
 | 
					                                                    'format' => 'rss')),
 | 
				
			||||||
                              // TRANS: Link for feed with replies for a user.
 | 
					                              // TRANS: Link for feed with replies for a user.
 | 
				
			||||||
                              // TRANS: %s is a user nickname.
 | 
					                              // TRANS: %s is a user nickname.
 | 
				
			||||||
                              sprintf(_('Replies feed for %s (RSS 2.0)'),
 | 
					                              sprintf(_('Replies feed for %s (RSS 2.0)'),
 | 
				
			||||||
                                      $this->user->nickname)),
 | 
					                                      $this->target->getNickname())),
 | 
				
			||||||
                     new Feed(Feed::ATOM,
 | 
					                     new Feed(Feed::ATOM,
 | 
				
			||||||
                              common_local_url('ApiTimelineMentions',
 | 
					                              common_local_url('ApiTimelineMentions',
 | 
				
			||||||
                                               array(
 | 
					                                               array(
 | 
				
			||||||
                                                    'id' => $this->user->nickname,
 | 
					                                                    'id' => $this->target->getNickname(),
 | 
				
			||||||
                                                    'format' => 'atom')),
 | 
					                                                    'format' => 'atom')),
 | 
				
			||||||
                              // TRANS: Link for feed with replies for a user.
 | 
					                              // TRANS: Link for feed with replies for a user.
 | 
				
			||||||
                              // TRANS: %s is a user nickname.
 | 
					                              // TRANS: %s is a user nickname.
 | 
				
			||||||
                              sprintf(_('Replies feed for %s (Atom)'),
 | 
					                              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()
 | 
					    function showContent()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
 | 
					        $nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
 | 
				
			||||||
@@ -195,33 +152,30 @@ class RepliesAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
 | 
					        $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
 | 
				
			||||||
                          $this->page, 'replies',
 | 
					                          $this->page, 'replies',
 | 
				
			||||||
                          array('nickname' => $this->user->nickname));
 | 
					                          array('nickname' => $this->target->getNickname()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showEmptyListMessage()
 | 
					    function showEmptyListMessage()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TRANS: Empty list message for page with replies for a user.
 | 
					        // TRANS: Empty list message for page with replies for a user.
 | 
				
			||||||
        // TRANS: %1$s and %s$s are the user nickname.
 | 
					        // TRANS: %1$s is 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.'),
 | 
					        $message = sprintf(_('This is the timeline showing replies to %1$s but no notices have arrived yet.'), $this->target->getNickname());
 | 
				
			||||||
                           $this->user->nickname,
 | 
					        $message .= ' ';    // Spacing between this sentence and the next.
 | 
				
			||||||
                           $this->user->nickname) . ' ';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (common_logged_in()) {
 | 
					        if (common_logged_in()) {
 | 
				
			||||||
            $current_user = common_current_user();
 | 
					            if ($this->target->getID() === $this->scoped->getID()) {
 | 
				
			||||||
            if ($this->user->id === $current_user->id) {
 | 
					 | 
				
			||||||
                // TRANS: Empty list message for page with replies for a user for the logged in user.
 | 
					                // 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).
 | 
					                // 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%%).');
 | 
					                $message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).');
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // TRANS: Empty list message for page with replies for a user for all logged in users but the user themselves.
 | 
					                // 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).
 | 
					                // 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](../%2$s) or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
 | 
					                $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: 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).
 | 
					            // 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');
 | 
					        $this->elementStart('div', 'guide');
 | 
				
			||||||
@@ -229,7 +183,7 @@ class RepliesAction extends Action
 | 
				
			|||||||
        $this->elementEnd('div');
 | 
					        $this->elementEnd('div');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function isReadOnly($args)
 | 
					    public function isReadOnly($args)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,7 +70,7 @@ class ShownoticeAction extends ManagedAction
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					        parent::prepare($args);
 | 
				
			||||||
        if ($this->boolean('ajax')) {
 | 
					        if ($this->boolean('ajax')) {
 | 
				
			||||||
            StatusNet::setApi(true);
 | 
					            GNUsocial::setApi(true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->notice = $this->getNotice();
 | 
					        $this->notice = $this->getNotice();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,15 +28,7 @@
 | 
				
			|||||||
 * @link      http://status.net/
 | 
					 * @link      http://status.net/
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
    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';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * User profile page
 | 
					 * User profile page
 | 
				
			||||||
@@ -233,10 +225,7 @@ class ShowstreamAction extends ProfileAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function showNotices()
 | 
					    function showNotices()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $pnl = null;
 | 
					        $pnl = new NoticeList($this->notice, $this);
 | 
				
			||||||
        if (Event::handle('ShowStreamNoticeList', array($this->notice, $this, &$pnl))) {
 | 
					 | 
				
			||||||
            $pnl = new ProfileNoticeList($this->notice, $this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $cnt = $pnl->show();
 | 
					        $cnt = $pnl->show();
 | 
				
			||||||
        if (0 == $cnt) {
 | 
					        if (0 == $cnt) {
 | 
				
			||||||
            $this->showEmptyListMessage();
 | 
					            $this->showEmptyListMessage();
 | 
				
			||||||
@@ -293,57 +282,3 @@ class ShowstreamAction extends ProfileAction
 | 
				
			|||||||
        return $options;
 | 
					        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');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,7 +122,7 @@ class SubscribeAction extends Action
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        // Throws exception on error
 | 
					        // Throws exception on error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $sub = Subscription::start($this->user->getProfile(),
 | 
					        $sub = Subscription::ensureStart($this->user->getProfile(),
 | 
				
			||||||
                                   $this->other);
 | 
					                                   $this->other);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->boolean('ajax')) {
 | 
					        if ($this->boolean('ajax')) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if (!defined('GNUSOCIAL')) { exit(1); }
 | 
					if (!defined('GNUSOCIAL')) { exit(1); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require_once INSTALLDIR . '/lib/settingsaction.php';
 | 
					 | 
				
			||||||
require_once INSTALLDIR . '/lib/peopletags.php';
 | 
					require_once INSTALLDIR . '/lib/peopletags.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TagprofileAction extends FormAction
 | 
					class TagprofileAction extends FormAction
 | 
				
			||||||
@@ -29,36 +28,32 @@ class TagprofileAction extends FormAction
 | 
				
			|||||||
    protected $target = null;
 | 
					    protected $target = null;
 | 
				
			||||||
    protected $form = 'TagProfile';
 | 
					    protected $form = 'TagProfile';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function prepare(array $args=array())
 | 
					    protected function doPreparation()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        parent::prepare($args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $id = $this->trimmed('id');
 | 
					        $id = $this->trimmed('id');
 | 
				
			||||||
        if (!$id) {
 | 
					        $uri = $this->trimmed('uri');
 | 
				
			||||||
            $this->target = null;
 | 
					        if (!empty($id))  {
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $this->target = Profile::getKV('id', $id);
 | 
					            $this->target = Profile::getKV('id', $id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!$this->target instanceof Profile) {
 | 
					            if (!$this->target instanceof Profile) {
 | 
				
			||||||
                // TRANS: Client error displayed when referring to non-existing profile ID.
 | 
					                // TRANS: Client error displayed when referring to non-existing profile ID.
 | 
				
			||||||
                $this->clientError(_('No profile with that 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.
 | 
					            // TRANS: Client error displayed when trying to tag a user that cannot be tagged.
 | 
				
			||||||
            $this->clientError(_('You cannot tag this user.'));
 | 
					            $this->clientError(_('You cannot tag this user.'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        $this->formOpts = $this->target;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function handle()
 | 
					        return true;
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (Event::handle('StartTagProfileAction', array($this, $this->target))) {
 | 
					 | 
				
			||||||
            parent::handle();
 | 
					 | 
				
			||||||
            Event::handle('EndTagProfileAction', array($this, $this->target));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function title()
 | 
					    function title()
 | 
				
			||||||
@@ -115,17 +110,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');
 | 
					        $tagstring = $this->trimmed('tags');
 | 
				
			||||||
        $token = $this->trimmed('token');
 | 
					        $token = $this->trimmed('token');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,22 +130,16 @@ class TagprofileAction extends FormAction
 | 
				
			|||||||
                    if (!common_valid_profile_tag($tag)) {
 | 
					                    if (!common_valid_profile_tag($tag)) {
 | 
				
			||||||
                        // TRANS: Form validation error displayed if a given tag is invalid.
 | 
					                        // TRANS: Form validation error displayed if a given tag is invalid.
 | 
				
			||||||
                        // TRANS: %s is the invalid tag.
 | 
					                        // TRANS: %s is the invalid tag.
 | 
				
			||||||
                        $this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
 | 
					                        throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag));
 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $tag_priv[$tag] = $private;
 | 
					                    $tag_priv[$tag] = $private;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            $result = Profile_tag::setTags($this->scoped->getID(), $this->target->getID(), $tags, $tag_priv);
 | 
				
			||||||
                $result = Profile_tag::setTags($this->scoped->id, $this->target->id, $tags, $tag_priv);
 | 
					 | 
				
			||||||
            if (!$result) {
 | 
					            if (!$result) {
 | 
				
			||||||
                    throw new Exception('The tags could not be saved.');
 | 
					                throw new ServerException('The tags could not be saved.');
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } catch (Exception $e) {
 | 
					 | 
				
			||||||
                $this->showForm($e->getMessage());
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->boolean('ajax')) {
 | 
					            if ($this->boolean('ajax')) {
 | 
				
			||||||
@@ -188,17 +168,4 @@ class TagprofileAction extends FormAction
 | 
				
			|||||||
            Event::handle('EndSavePeopletags', array($this, $tagstring));
 | 
					            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');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ class Attention extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'attention';  // table name
 | 
					    public $__table = 'attention';  // table name
 | 
				
			||||||
    public $notice_id;              // int(4) primary_key not_null
 | 
					    public $notice_id;              // int(4) primary_key not_null
 | 
				
			||||||
    public $profile_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 $created;                // datetime()   not_null
 | 
				
			||||||
    public $modified;               // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;               // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,7 +33,7 @@ class Attention extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice_id to give attention'),
 | 
					                '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'),
 | 
					                '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'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,8 +15,8 @@ class Avatar extends Managed_DataObject
 | 
				
			|||||||
    public $width;                           // int(4)  primary_key not_null
 | 
					    public $width;                           // int(4)  primary_key not_null
 | 
				
			||||||
    public $height;                          // int(4)  primary_key not_null
 | 
					    public $height;                          // int(4)  primary_key not_null
 | 
				
			||||||
    public $mediatype;                       // varchar(32)   not_null
 | 
					    public $mediatype;                       // varchar(32)   not_null
 | 
				
			||||||
    public $filename;                        // varchar(255)
 | 
					    public $filename;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $url;                             // varchar(255)  unique_key
 | 
					    public $url;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,14 +32,14 @@ class Avatar extends Managed_DataObject
 | 
				
			|||||||
                'width' => array('type' => 'int', 'not null' => true, 'description' => 'image width'),
 | 
					                'width' => array('type' => 'int', 'not null' => true, 'description' => 'image width'),
 | 
				
			||||||
                'height' => array('type' => 'int', 'not null' => true, 'description' => 'image height'),
 | 
					                'height' => array('type' => 'int', 'not null' => true, 'description' => 'image height'),
 | 
				
			||||||
                'mediatype' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'file type'),
 | 
					                'mediatype' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'file type'),
 | 
				
			||||||
                'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'local filename, if local'),
 | 
					                'filename' => array('type' => 'varchar', 'length' => 191, 'description' => 'local filename, if local'),
 | 
				
			||||||
                'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'avatar location'),
 | 
					                'url' => array('type' => 'text', 'description' => 'avatar location, not indexed - do not use in WHERE statement'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'primary key' => array('profile_id', 'width', 'height'),
 | 
					            'primary key' => array('profile_id', 'width', 'height'),
 | 
				
			||||||
            'unique keys' => array(
 | 
					            'unique keys' => array(
 | 
				
			||||||
                'avatar_url_key' => array('url'),
 | 
					//                'avatar_filename_key' => array('filename'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'foreign keys' => array(
 | 
					            'foreign keys' => array(
 | 
				
			||||||
                'avatar_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
 | 
					                'avatar_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
 | 
				
			||||||
@@ -241,16 +241,21 @@ class Avatar extends Managed_DataObject
 | 
				
			|||||||
            // TRANS: An error message when avatar size is unreasonable
 | 
					            // TRANS: An error message when avatar size is unreasonable
 | 
				
			||||||
            throw new Exception(_m('Avatar size too large'));
 | 
					            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);
 | 
					        $original = Avatar::getUploaded($target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $imagefile = new ImageFile($target->id, Avatar::path($original->filename));
 | 
					        $imagefile = new ImageFile(null, Avatar::path($original->filename));
 | 
				
			||||||
        $filename = $imagefile->resize($width);
 | 
					        $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 = clone($original);
 | 
				
			||||||
        $scaled->original = false;
 | 
					        $scaled->original = false;
 | 
				
			||||||
        $scaled->width = $width;
 | 
					        $scaled->width = $width;
 | 
				
			||||||
        $scaled->height = $width;
 | 
					        $scaled->height = $height;
 | 
				
			||||||
        $scaled->url = Avatar::url($filename);
 | 
					        $scaled->url = Avatar::url($filename);
 | 
				
			||||||
        $scaled->filename = $filename;
 | 
					        $scaled->filename = $filename;
 | 
				
			||||||
        $scaled->created = common_sql_now();
 | 
					        $scaled->created = common_sql_now();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ class Config extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'config';                          // table name
 | 
					    public $__table = 'config';                          // table name
 | 
				
			||||||
    public $section;                         // varchar(32)  primary_key not_null
 | 
					    public $section;                         // varchar(32)  primary_key not_null
 | 
				
			||||||
    public $setting;                         // varchar(32)  primary_key not_null
 | 
					    public $setting;                         // varchar(32)  primary_key not_null
 | 
				
			||||||
    public $value;                           // varchar(255)
 | 
					    public $value;                           // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* the code above is auto generated do not remove the tag below */
 | 
					    /* the code above is auto generated do not remove the tag below */
 | 
				
			||||||
    ###END_AUTOCODE
 | 
					    ###END_AUTOCODE
 | 
				
			||||||
@@ -46,7 +46,7 @@ class Config extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'section' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration section'),
 | 
					                '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'),
 | 
					                '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' => 'varchar', 'length' => 191, 'description' => 'configuration value'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'primary key' => array('section', 'setting'),
 | 
					            'primary key' => array('section', 'setting'),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ class Confirm_address extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'confirm_address';                 // table name
 | 
					    public $__table = 'confirm_address';                 // table name
 | 
				
			||||||
    public $code;                            // varchar(32)  primary_key not_null
 | 
					    public $code;                            // varchar(32)  primary_key not_null
 | 
				
			||||||
    public $user_id;                         // int(4)   not_null
 | 
					    public $user_id;                         // int(4)   not_null
 | 
				
			||||||
    public $address;                         // varchar(255)   not_null
 | 
					    public $address;                         // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $address_extra;                   // varchar(255)   not_null
 | 
					    public $address_extra;                   // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $address_type;                    // varchar(8)   not_null
 | 
					    public $address_type;                    // varchar(8)   not_null
 | 
				
			||||||
    public $claimed;                         // datetime()  
 | 
					    public $claimed;                         // datetime()  
 | 
				
			||||||
    public $sent;                            // datetime()  
 | 
					    public $sent;                            // datetime()  
 | 
				
			||||||
@@ -28,8 +28,8 @@ class Confirm_address extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'good random code'),
 | 
					                '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'),
 | 
					                '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' => array('type' => 'varchar', 'length' => 191, '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_extra' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'carrier ID, for SMS'),
 | 
				
			||||||
                'address_type' => array('type' => 'varchar', 'length' => 8, 'not null' => true, 'description' => 'address type ("email", "xmpp", "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'),
 | 
					                'claimed' => array('type' => 'datetime', 'description' => 'date this was claimed for queueing'),
 | 
				
			||||||
                'sent' => array('type' => 'datetime', 'description' => 'date this was sent for queueing'),
 | 
					                'sent' => array('type' => 'datetime', 'description' => 'date this was sent for queueing'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,8 +10,8 @@ class Consumer extends Managed_DataObject
 | 
				
			|||||||
    /* the code below is auto generated do not remove the above tag */
 | 
					    /* the code below is auto generated do not remove the above tag */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $__table = 'consumer';                        // table name
 | 
					    public $__table = 'consumer';                        // table name
 | 
				
			||||||
    public $consumer_key;                    // varchar(255)  primary_key not_null
 | 
					    public $consumer_key;                    // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $consumer_secret;                 // varchar(255)   not_null
 | 
					    public $consumer_secret;                 // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $seed;                            // char(32)   not_null
 | 
					    public $seed;                            // char(32)   not_null
 | 
				
			||||||
    public $created;                         // datetime   not_null
 | 
					    public $created;                         // datetime   not_null
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
@@ -24,8 +24,8 @@ class Consumer extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'description' => 'OAuth consumer record',
 | 
					            'description' => 'OAuth consumer record',
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'consumer_key' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
					                'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
				
			||||||
                'consumer_secret' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'secret value'),
 | 
					                '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'),
 | 
					                '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'),
 | 
					                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ class Conversation extends Managed_DataObject
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public $__table = 'conversation';        // table name
 | 
					    public $__table = 'conversation';        // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime   not_null
 | 
					    public $created;                         // datetime   not_null
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +44,7 @@ class Conversation extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'should be set from root notice id (since 2014-03-01 commit)'),
 | 
					                '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'),
 | 
					                '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'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ class Deleted_notice extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'deleted_notice';                  // table name
 | 
					    public $__table = 'deleted_notice';                  // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $profile_id;                      // int(4)   not_null
 | 
					    public $profile_id;                      // int(4)   not_null
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $deleted;                         // datetime()   not_null
 | 
					    public $deleted;                         // datetime()   not_null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,7 +47,7 @@ class Deleted_notice extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'identity of notice'),
 | 
					                'id' => array('type' => 'int', 'not null' => true, 'description' => 'identity of notice'),
 | 
				
			||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'author of the 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'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created'),
 | 
					                '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'),
 | 
					                'deleted' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										219
									
								
								classes/File.php
									
									
									
									
									
								
							
							
						
						@@ -26,29 +26,36 @@ class File extends Managed_DataObject
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public $__table = 'file';                            // table name
 | 
					    public $__table = 'file';                            // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    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 $mimetype;                        // varchar(50)
 | 
				
			||||||
    public $size;                            // int(4)
 | 
					    public $size;                            // int(4)
 | 
				
			||||||
    public $title;                           // varchar(255)
 | 
					    public $title;                           // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $date;                            // int(4)
 | 
					    public $date;                            // int(4)
 | 
				
			||||||
    public $protected;                       // int(4)
 | 
					    public $protected;                       // int(4)
 | 
				
			||||||
    public $filename;                        // varchar(255)
 | 
					    public $filename;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $width;                           // int(4)
 | 
					    public $width;                           // int(4)
 | 
				
			||||||
    public $height;                          // int(4)
 | 
					    public $height;                          // int(4)
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const URLHASH_ALG = 'sha256';
 | 
				
			||||||
 | 
					    const FILEHASH_ALG = 'sha256';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function schemaDef()
 | 
					    public static function schemaDef()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'serial', 'not null' => true),
 | 
					                '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'),
 | 
					                'mimetype' => array('type' => 'varchar', 'length' => 50, 'description' => 'mime type of resource'),
 | 
				
			||||||
                'size' => array('type' => 'int', 'description' => 'size of resource when available'),
 | 
					                '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' => 'varchar', 'length' => 191, 'description' => 'title of resource when available'),
 | 
				
			||||||
                'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
 | 
					                'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
 | 
				
			||||||
                'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'),
 | 
					                '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' => 'varchar', 'length' => 191, 'description' => 'if a local file, name of the file'),
 | 
				
			||||||
                'width' => array('type' => 'int', 'description' => 'width in pixels, if it can be described as such and data is available'),
 | 
					                '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'),
 | 
					                'height' => array('type' => 'int', 'description' => 'height in pixels, if it can be described as such and data is available'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,7 +63,10 @@ class File extends Managed_DataObject
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'primary key' => array('id'),
 | 
					            'primary key' => array('id'),
 | 
				
			||||||
            'unique keys' => array(
 | 
					            'unique keys' => array(
 | 
				
			||||||
                'file_url_key' => array('url'),
 | 
					                'file_urlhash_key' => array('urlhash'),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            'indexes' => array(
 | 
				
			||||||
 | 
					                'file_filehash_idx' => array('filehash'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -77,10 +87,11 @@ class File extends Managed_DataObject
 | 
				
			|||||||
        // I don't know why we have to keep doing this but I'm adding this last check to avoid
 | 
					        // I don't know why we have to keep doing this but I'm adding this last check to avoid
 | 
				
			||||||
        // uniqueness bugs.
 | 
					        // uniqueness bugs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file = File::getKV('url', $given_url);
 | 
					        $file = File::getKV('urlhash', self::hashurl($given_url));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (!$file instanceof File) {
 | 
					        if (!$file instanceof File) {
 | 
				
			||||||
            $file = new File;
 | 
					            $file = new File;
 | 
				
			||||||
 | 
					            $file->urlhash = self::hashurl($given_url);
 | 
				
			||||||
            $file->url = $given_url;
 | 
					            $file->url = $given_url;
 | 
				
			||||||
            if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected'];
 | 
					            if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected'];
 | 
				
			||||||
            if (!empty($redir_data['title'])) $file->title = $redir_data['title'];
 | 
					            if (!empty($redir_data['title'])) $file->title = $redir_data['title'];
 | 
				
			||||||
@@ -122,16 +133,23 @@ class File extends Managed_DataObject
 | 
				
			|||||||
            throw new ServerException('No canonical URL from given URL to process');
 | 
					            throw new ServerException('No canonical URL from given URL to process');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $file = File::getKV('url', $given_url);
 | 
					        $file = null;
 | 
				
			||||||
        if (!$file instanceof File) {
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $file = File::getByUrl($given_url);
 | 
				
			||||||
 | 
					        } catch (NoResultException $e) {
 | 
				
			||||||
            // First check if we have a lookup trace for this URL already
 | 
					            // First check if we have a lookup trace for this URL already
 | 
				
			||||||
            $file_redir = File_redirection::getKV('url', $given_url);
 | 
					            try {
 | 
				
			||||||
            if ($file_redir instanceof File_redirection) {
 | 
					                $file_redir = File_redirection::getByUrl($given_url);
 | 
				
			||||||
                $file = File::getKV('id', $file_redir->file_id);
 | 
					                $file = File::getKV('id', $file_redir->file_id);
 | 
				
			||||||
                if (!$file instanceof File) {
 | 
					                if (!$file instanceof File) {
 | 
				
			||||||
                    // File did not exist, let's clean up the File_redirection entry
 | 
					                    // File did not exist, let's clean up the File_redirection entry
 | 
				
			||||||
                    $file_redir->delete();
 | 
					                    $file_redir->delete();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            } catch (NoResultException $e) {
 | 
				
			||||||
 | 
					                // We just wanted to doublecheck whether a File_thumbnail we might've had
 | 
				
			||||||
 | 
					                // actually referenced an existing File object.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If we still don't have a File object, let's create one now!
 | 
					        // If we still don't have a File object, let's create one now!
 | 
				
			||||||
@@ -151,8 +169,7 @@ class File extends Managed_DataObject
 | 
				
			|||||||
                throw new ServerException(sprintf(_("Cannot process URL '%s'"), $given_url));
 | 
					                throw new ServerException(sprintf(_("Cannot process URL '%s'"), $given_url));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // TODO: max field length
 | 
					            if ($redir_url === $given_url || !$followRedirects) {
 | 
				
			||||||
                if ($redir_url === $given_url || strlen($redir_url) > 255 || !$followRedirects) {
 | 
					 | 
				
			||||||
                // Save the File object based on our lookup trace
 | 
					                // Save the File object based on our lookup trace
 | 
				
			||||||
                $file = File::saveNew($redir_data, $given_url);
 | 
					                $file = File::saveNew($redir_data, $given_url);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@@ -167,7 +184,6 @@ class File extends Managed_DataObject
 | 
				
			|||||||
                $file = self::processNew($redir_url, $notice_id, /*followRedirects*/false);
 | 
					                $file = self::processNew($redir_url, $notice_id, /*followRedirects*/false);
 | 
				
			||||||
                File_redirection::saveNew($redir_data, $file->id, $given_url);
 | 
					                File_redirection::saveNew($redir_data, $file->id, $given_url);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!$file instanceof File) {
 | 
					            if (!$file instanceof File) {
 | 
				
			||||||
                // This should only happen if File::saveNew somehow did not return a File object,
 | 
					                // This should only happen if File::saveNew somehow did not return a File object,
 | 
				
			||||||
@@ -237,12 +253,7 @@ class File extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static function filename(Profile $profile, $origname, $mimetype)
 | 
					    static function filename(Profile $profile, $origname, $mimetype)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try {
 | 
					        $ext = self::guessMimeExtension($mimetype);
 | 
				
			||||||
            $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);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Normalize and make the original filename more URL friendly.
 | 
					        // Normalize and make the original filename more URL friendly.
 | 
				
			||||||
        $origname = basename($origname, ".$ext");
 | 
					        $origname = basename($origname, ".$ext");
 | 
				
			||||||
@@ -263,6 +274,17 @@ class File extends Managed_DataObject
 | 
				
			|||||||
        return $filename;
 | 
					        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
 | 
				
			||||||
 | 
					            $ext = substr(strrchr($mimetype, '/'), 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return strtolower($ext);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Validation for as-saved base filenames
 | 
					     * Validation for as-saved base filenames
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -303,7 +325,7 @@ class File extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (StatusNet::useHTTPS()) {
 | 
					        if (GNUsocial::useHTTPS()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $sslserver = common_config('attachments', 'sslserver');
 | 
					            $sslserver = common_config('attachments', 'sslserver');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -381,6 +403,10 @@ class File extends Managed_DataObject
 | 
				
			|||||||
     * @param $crop   bool  Crop to the max-values' aspect ratio
 | 
					     * @param $crop   bool  Crop to the max-values' aspect ratio
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return File_thumbnail
 | 
					     * @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)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -394,67 +420,16 @@ class File extends Managed_DataObject
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($width === null) {
 | 
					        return $image->getFileThumbnail($width, $height, $crop);
 | 
				
			||||||
            $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);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getPath()
 | 
					    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()
 | 
				
			||||||
@@ -462,7 +437,7 @@ class File extends Managed_DataObject
 | 
				
			|||||||
        if (!empty($this->filename)) {
 | 
					        if (!empty($this->filename)) {
 | 
				
			||||||
            // A locally stored file, so let's generate a URL for our instance.
 | 
					            // A locally stored file, so let's generate a URL for our instance.
 | 
				
			||||||
            $url = self::url($this->filename);
 | 
					            $url = self::url($this->filename);
 | 
				
			||||||
            if ($url != $this->url) {
 | 
					            if (self::hashurl($url) !== $this->urlhash) {
 | 
				
			||||||
                // For indexing purposes, in case we do a lookup on the 'url' field.
 | 
					                // 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
 | 
					                // also we're fixing possible changes from http to https, or paths
 | 
				
			||||||
                $this->updateUrl($url);
 | 
					                $this->updateUrl($url);
 | 
				
			||||||
@@ -474,16 +449,40 @@ class File extends Managed_DataObject
 | 
				
			|||||||
        return $this->url;
 | 
					        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, $alg=File::FILEHASH_ALG)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $file = new File();
 | 
				
			||||||
 | 
					        $file->filehash = strtolower($hashstr);
 | 
				
			||||||
 | 
					        if (!$file->find(true)) {
 | 
				
			||||||
 | 
					            throw new NoResultException($file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $file;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function updateUrl($url)
 | 
					    public function updateUrl($url)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $file = File::getKV('url', $url);
 | 
					        $file = File::getKV('urlhash', self::hashurl($url));
 | 
				
			||||||
        if ($file instanceof File) {
 | 
					        if ($file instanceof File) {
 | 
				
			||||||
            throw new ServerException('URL already exists in DB');
 | 
					            throw new ServerException('URL already exists in DB');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $sql = 'UPDATE %1$s SET url=%2$s WHERE url=%3$s;';
 | 
					        $sql = 'UPDATE %1$s SET urlhash=%2$s, url=%3$s WHERE urlhash=%4$s;';
 | 
				
			||||||
        $result = $this->query(sprintf($sql, $this->__table,
 | 
					        $result = $this->query(sprintf($sql, $this->__table,
 | 
				
			||||||
 | 
					                                             $this->_quote((string)self::hashurl($url)),
 | 
				
			||||||
                                             $this->_quote((string)$url),
 | 
					                                             $this->_quote((string)$url),
 | 
				
			||||||
                                             $this->_quote((string)$this->url)));
 | 
					                                             $this->_quote((string)$this->urlhash)));
 | 
				
			||||||
        if ($result === false) {
 | 
					        if ($result === false) {
 | 
				
			||||||
            common_log_db_error($this, 'UPDATE', __FILE__);
 | 
					            common_log_db_error($this, 'UPDATE', __FILE__);
 | 
				
			||||||
            throw new ServerException("Could not UPDATE {$this->__table}.url");
 | 
					            throw new ServerException("Could not UPDATE {$this->__table}.url");
 | 
				
			||||||
@@ -502,9 +501,9 @@ class File extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function blowCache($last=false)
 | 
					    function blowCache($last=false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        self::blow('file:notice-ids:%s', $this->url);
 | 
					        self::blow('file:notice-ids:%s', $this->urlhash);
 | 
				
			||||||
        if ($last) {
 | 
					        if ($last) {
 | 
				
			||||||
            self::blow('file:notice-ids:%s;last', $this->url);
 | 
					            self::blow('file:notice-ids:%s;last', $this->urlhash);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self::blow('file:notice-count:%d', $this->id);
 | 
					        self::blow('file:notice-count:%d', $this->id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -582,4 +581,54 @@ class File extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return $title ?: null;
 | 
					        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...";
 | 
				
			||||||
 | 
					        // 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 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...";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,8 @@ class File_redirection extends Managed_DataObject
 | 
				
			|||||||
    /* the code below is auto generated do not remove the above tag */
 | 
					    /* the code below is auto generated do not remove the above tag */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $__table = 'file_redirection';                // table name
 | 
					    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 $file_id;                         // int(4)
 | 
				
			||||||
    public $redirections;                    // int(4)
 | 
					    public $redirections;                    // int(4)
 | 
				
			||||||
    public $httpcode;                        // int(4)
 | 
					    public $httpcode;                        // int(4)
 | 
				
			||||||
@@ -42,19 +43,30 @@ class File_redirection extends Managed_DataObject
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => 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'),
 | 
					                'file_id' => array('type' => 'int', 'description' => 'short URL for what URL/file'),
 | 
				
			||||||
                'redirections' => array('type' => 'int', 'description' => 'redirect count'),
 | 
					                'redirections' => array('type' => 'int', 'description' => 'redirect count'),
 | 
				
			||||||
                'httpcode' => array('type' => 'int', 'description' => 'HTTP status code (20x, 30x, etc.)'),
 | 
					                'httpcode' => array('type' => 'int', 'description' => 'HTTP status code (20x, 30x, etc.)'),
 | 
				
			||||||
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'primary key' => array('url'),
 | 
					            'primary key' => array('urlhash'),
 | 
				
			||||||
            'foreign keys' => array(
 | 
					            'foreign keys' => array(
 | 
				
			||||||
                'file_redirection_file_id_fkey' => array('file' => array('file_id' => 'id')),
 | 
					                'file_redirection_file_id_fkey' => array('file' => array('file_id' => 'id')),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static public function getByUrl($url)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $file = new File_redirection();
 | 
				
			||||||
 | 
					        $file->urlhash = File::hashurl($url);
 | 
				
			||||||
 | 
					        if (!$file->find(true)) {
 | 
				
			||||||
 | 
					            throw new NoResultException($file);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $file;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static function _commonHttp($url, $redirs) {
 | 
					    static function _commonHttp($url, $redirs) {
 | 
				
			||||||
        $request = new HTTPClient($url);
 | 
					        $request = new HTTPClient($url);
 | 
				
			||||||
        $request->setConfig(array(
 | 
					        $request->setConfig(array(
 | 
				
			||||||
@@ -161,17 +173,18 @@ class File_redirection extends Managed_DataObject
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function where($in_url, $discover=true) {
 | 
					    public function where($in_url, $discover=true) {
 | 
				
			||||||
        // let's see if we know this...
 | 
					        // let's see if we know this...
 | 
				
			||||||
        $a = File::getKV('url', $in_url);
 | 
					        try {
 | 
				
			||||||
 | 
					            $a = File::getByUrl($in_url);
 | 
				
			||||||
        if (!empty($a)) {
 | 
					 | 
				
			||||||
            // this is a direct link to $a->url
 | 
					            // this is a direct link to $a->url
 | 
				
			||||||
            return $a->url;
 | 
					            return $a->url;
 | 
				
			||||||
        } else {
 | 
					        } catch (NoResultException $e) {
 | 
				
			||||||
            $b = File_redirection::getKV('url', $in_url);
 | 
					            try {
 | 
				
			||||||
            if (!empty($b)) {
 | 
					                $b = File_redirection::getByUrl($in_url);
 | 
				
			||||||
                // this is a redirect to $b->file_id
 | 
					                // this is a redirect to $b->file_id
 | 
				
			||||||
                $a = File::getKV('id', $b->file_id);
 | 
					                $a = File::getKV('id', $b->file_id);
 | 
				
			||||||
                return $a->url;
 | 
					                return $a->url;
 | 
				
			||||||
 | 
					            } catch (NoResultException $e) {
 | 
				
			||||||
 | 
					                // Oh well, let's keep going
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -274,6 +287,7 @@ class File_redirection extends Managed_DataObject
 | 
				
			|||||||
            $file_redir = File_redirection::getKV('url', $short_url);
 | 
					            $file_redir = File_redirection::getKV('url', $short_url);
 | 
				
			||||||
            if (!$file_redir instanceof File_redirection) {
 | 
					            if (!$file_redir instanceof File_redirection) {
 | 
				
			||||||
                $file_redir = new File_redirection;
 | 
					                $file_redir = new File_redirection;
 | 
				
			||||||
 | 
					                $file_redir->urlhash = File::hashurl($short_url);
 | 
				
			||||||
                $file_redir->url = $short_url;
 | 
					                $file_redir->url = $short_url;
 | 
				
			||||||
                $file_redir->file_id = $file_id;
 | 
					                $file_redir->file_id = $file_id;
 | 
				
			||||||
                $file_redir->insert();
 | 
					                $file_redir->insert();
 | 
				
			||||||
@@ -334,10 +348,53 @@ class File_redirection extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function saveNew($data, $file_id, $url) {
 | 
					    function saveNew($data, $file_id, $url) {
 | 
				
			||||||
        $file_redir = new File_redirection;
 | 
					        $file_redir = new File_redirection;
 | 
				
			||||||
 | 
					        $file_redir->urlhash = File::hashurl($short_url);
 | 
				
			||||||
        $file_redir->url = $url;
 | 
					        $file_redir->url = $url;
 | 
				
			||||||
        $file_redir->file_id = $file_id;
 | 
					        $file_redir->file_id = $file_id;
 | 
				
			||||||
        $file_redir->redirections = intval($data['redirects']);
 | 
					        $file_redir->redirections = intval($data['redirects']);
 | 
				
			||||||
        $file_redir->httpcode = intval($data['code']);
 | 
					        $file_redir->httpcode = intval($data['code']);
 | 
				
			||||||
        $file_redir->insert();
 | 
					        $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...";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,8 +27,8 @@ class File_thumbnail extends Managed_DataObject
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public $__table = 'file_thumbnail';                  // table name
 | 
					    public $__table = 'file_thumbnail';                  // table name
 | 
				
			||||||
    public $file_id;                         // int(4)  primary_key not_null
 | 
					    public $file_id;                         // int(4)  primary_key not_null
 | 
				
			||||||
    public $url;                             // varchar(255)  unique_key
 | 
					    public $url;                             // text
 | 
				
			||||||
    public $filename;                        // varchar(255)
 | 
					    public $filename;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $width;                           // int(4)  primary_key
 | 
					    public $width;                           // int(4)  primary_key
 | 
				
			||||||
    public $height;                          // int(4)  primary_key
 | 
					    public $height;                          // int(4)  primary_key
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
@@ -38,8 +38,8 @@ class File_thumbnail extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'file_id' => array('type' => 'int', 'not null' => true, 'description' => 'thumbnail for what URL/file'),
 | 
					                'file_id' => array('type' => 'int', 'not null' => true, 'description' => 'thumbnail for what URL/file'),
 | 
				
			||||||
                'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of thumbnail'),
 | 
					                'url' => array('type' => 'text', 'not null' => false, 'description' => 'URL of thumbnail'),
 | 
				
			||||||
                'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if stored locally, filename is put here'),
 | 
					                'filename' => array('type' => 'varchar', 'length' => 191, 'description' => 'if stored locally, filename is put here'),
 | 
				
			||||||
                'width' => array('type' => 'int', 'description' => 'width of thumbnail'),
 | 
					                'width' => array('type' => 'int', 'description' => 'width of thumbnail'),
 | 
				
			||||||
                'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
 | 
					                'height' => array('type' => 'int', 'description' => 'height of thumbnail'),
 | 
				
			||||||
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
@@ -117,46 +117,42 @@ class File_thumbnail extends Managed_DataObject
 | 
				
			|||||||
        return File::path($filename);
 | 
					        return File::path($filename);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static function url($filename)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // TODO: Store thumbnails in their own directory and don't use File::url here
 | 
				
			||||||
 | 
					        return File::url($filename);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function getPath()
 | 
					    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()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!empty($this->getFile()->filename)) {
 | 
					        if (!empty($this->getFile()->filename)) {
 | 
				
			||||||
            // A locally stored File, so let's generate a URL for our instance.
 | 
					            // A locally stored File, so we can dynamically generate a URL.
 | 
				
			||||||
            $url = File::url($this->filename);
 | 
					            if (!empty($this->url)) {
 | 
				
			||||||
            if ($url != $this->url) {
 | 
					                // Let's just clear this field as there is no point in having it for local files.
 | 
				
			||||||
                // For indexing purposes, in case we do a lookup on the 'url' field.
 | 
					                $orig = clone($this);
 | 
				
			||||||
                // also we're fixing possible changes from http to https, or paths
 | 
					                $this->url = null;
 | 
				
			||||||
                $this->updateUrl($url);
 | 
					                $this->update($orig);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return $url;
 | 
					            $url = common_local_url('attachment_thumbnail', array('attachment'=>$this->file_id));
 | 
				
			||||||
 | 
					            if (strpos($url, '?') === false) {
 | 
				
			||||||
 | 
					                $url .= '?';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return $url . http_build_query(array('w'=>$this->width, 'h'=>$this->height));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // No local filename available, return the URL we have stored
 | 
					        // No local filename available, return the URL we have stored
 | 
				
			||||||
        return $this->url;
 | 
					        return $this->url;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function updateUrl($url)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $file = File_thumbnail::getKV('url', $url);
 | 
					 | 
				
			||||||
        if ($file instanceof File_thumbnail) {
 | 
					 | 
				
			||||||
            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,
 | 
					 | 
				
			||||||
                                             $this->_quote((string)$url),
 | 
					 | 
				
			||||||
                                             $this->_quote((string)$this->url)));
 | 
					 | 
				
			||||||
        if ($result === false) {
 | 
					 | 
				
			||||||
            common_log_db_error($this, 'UPDATE', __FILE__);
 | 
					 | 
				
			||||||
            throw new ServerException("Could not UPDATE {$this->__table}.url");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return $result;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public function delete($useWhere=false)
 | 
					    public function delete($useWhere=false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!empty($this->filename) && file_exists(File_thumbnail::path($this->filename))) {
 | 
					        if (!empty($this->filename) && file_exists(File_thumbnail::path($this->filename))) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ class Foreign_link extends Managed_DataObject
 | 
				
			|||||||
    public $user_id;                         // int(4)  primary_key not_null
 | 
					    public $user_id;                         // int(4)  primary_key not_null
 | 
				
			||||||
    public $foreign_id;                      // bigint(8)  primary_key not_null unsigned
 | 
					    public $foreign_id;                      // bigint(8)  primary_key not_null unsigned
 | 
				
			||||||
    public $service;                         // int(4)  primary_key not_null
 | 
					    public $service;                         // int(4)  primary_key not_null
 | 
				
			||||||
    public $credentials;                     // varchar(255)
 | 
					    public $credentials;                     // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $noticesync;                      // tinyint(1)   not_null default_1
 | 
					    public $noticesync;                      // tinyint(1)   not_null default_1
 | 
				
			||||||
    public $friendsync;                      // tinyint(1)   not_null default_2
 | 
					    public $friendsync;                      // tinyint(1)   not_null default_2
 | 
				
			||||||
    public $profilesync;                     // tinyint(1)   not_null default_1
 | 
					    public $profilesync;                     // tinyint(1)   not_null default_1
 | 
				
			||||||
@@ -32,7 +32,7 @@ class Foreign_link extends Managed_DataObject
 | 
				
			|||||||
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'link to user on this system, if exists'),
 | 
					                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'link to user on this system, if exists'),
 | 
				
			||||||
                'foreign_id' => array('type' => 'int', 'size' => 'big', 'unsigned' => true, 'not null' => true, 'description' => 'link to user on foreign service, if exists'),
 | 
					                'foreign_id' => array('type' => 'int', 'size' => 'big', 'unsigned' => true, 'not null' => true, 'description' => 'link to user on foreign service, if exists'),
 | 
				
			||||||
                'service' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to service'),
 | 
					                'service' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to service'),
 | 
				
			||||||
                'credentials' => array('type' => 'varchar', 'length' => 255, 'description' => 'authc credentials, typically a password'),
 | 
					                'credentials' => array('type' => 'varchar', 'length' => 191, 'description' => 'authc credentials, typically a password'),
 | 
				
			||||||
                'noticesync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'notice synchronization, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies'),
 | 
					                'noticesync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'notice synchronization, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies'),
 | 
				
			||||||
                'friendsync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 2, 'description' => 'friend synchronization, bit 1 = sync outgoing, bit 2 = sync incoming'),
 | 
					                'friendsync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 2, 'description' => 'friend synchronization, bit 1 = sync outgoing, bit 2 = sync incoming'),
 | 
				
			||||||
                'profilesync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming'),
 | 
					                'profilesync' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Foreign_service extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'foreign_service';                 // table name
 | 
					    public $__table = 'foreign_service';                 // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $name;                            // varchar(32)  unique_key not_null
 | 
					    public $name;                            // varchar(32)  unique_key not_null
 | 
				
			||||||
    public $description;                     // varchar(255)
 | 
					    public $description;                     // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,7 +25,7 @@ class Foreign_service extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'numeric key for service'),
 | 
					                'id' => array('type' => 'int', 'not null' => true, 'description' => 'numeric key for service'),
 | 
				
			||||||
                'name' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'name of the service'),
 | 
					                'name' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'name of the service'),
 | 
				
			||||||
                'description' => array('type' => 'varchar', 'length' => 255, 'description' => 'description'),
 | 
					                'description' => array('type' => 'varchar', 'length' => 191, 'description' => 'description'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ class Foreign_user extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'foreign_user';                    // table name
 | 
					    public $__table = 'foreign_user';                    // table name
 | 
				
			||||||
    public $id;                              // bigint(8)  primary_key not_null
 | 
					    public $id;                              // bigint(8)  primary_key not_null
 | 
				
			||||||
    public $service;                         // int(4)  primary_key not_null
 | 
					    public $service;                         // int(4)  primary_key not_null
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key not_null
 | 
					    public $uri;                             // varchar(191)  unique_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $nickname;                        // varchar(255)
 | 
					    public $nickname;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,8 +26,8 @@ class Foreign_user extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'size' => 'big', 'not null' => true, 'description' => 'unique numeric key on foreign service'),
 | 
					                'id' => array('type' => 'int', 'size' => 'big', 'not null' => true, 'description' => 'unique numeric key on foreign service'),
 | 
				
			||||||
                'service' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to service'),
 | 
					                'service' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to service'),
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'identifying URI'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'identifying URI'),
 | 
				
			||||||
                'nickname' => array('type' => 'varchar', 'length' => 255, 'description' => 'nickname on foreign service'),
 | 
					                'nickname' => array('type' => 'varchar', 'length' => 191, 'description' => 'nickname on foreign service'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Group_member extends Managed_DataObject
 | 
				
			|||||||
    public $group_id;                        // int(4)  primary_key not_null
 | 
					    public $group_id;                        // int(4)  primary_key not_null
 | 
				
			||||||
    public $profile_id;                      // int(4)  primary_key not_null
 | 
					    public $profile_id;                      // int(4)  primary_key not_null
 | 
				
			||||||
    public $is_admin;                        // tinyint(1)
 | 
					    public $is_admin;                        // tinyint(1)
 | 
				
			||||||
    public $uri;                             // varchar(255)
 | 
					    public $uri;                             // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,7 +26,7 @@ class Group_member extends Managed_DataObject
 | 
				
			|||||||
                'group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'),
 | 
					                'group_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to user_group'),
 | 
				
			||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
				
			||||||
                'is_admin' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this user an admin?'),
 | 
					                'is_admin' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'is this user an admin?'),
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universal identifier'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Invitation extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'invitation';                      // table name
 | 
					    public $__table = 'invitation';                      // table name
 | 
				
			||||||
    public $code;                            // varchar(32)  primary_key not_null
 | 
					    public $code;                            // varchar(32)  primary_key not_null
 | 
				
			||||||
    public $user_id;                         // int(4)   not_null
 | 
					    public $user_id;                         // int(4)   not_null
 | 
				
			||||||
    public $address;                         // varchar(255)  multiple_key not_null
 | 
					    public $address;                         // varchar(191)  multiple_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $address_type;                    // varchar(8)  multiple_key not_null
 | 
					    public $address_type;                    // varchar(8)  multiple_key not_null
 | 
				
			||||||
    public $registered_user_id;              // int(4)   not_null
 | 
					    public $registered_user_id;              // int(4)   not_null
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
@@ -34,7 +34,7 @@ class Invitation extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'random code for an invitation'),
 | 
					                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'random code for an invitation'),
 | 
				
			||||||
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'who sent the invitation'),
 | 
					                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'who sent the invitation'),
 | 
				
			||||||
                'address' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'invitation sent to'),
 | 
					                'address' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'invitation sent to'),
 | 
				
			||||||
                'address_type' => array('type' => 'varchar', 'length' => 8, 'not null' => true, 'description' => 'address type ("email", "xmpp", "sms")'),
 | 
					                'address_type' => array('type' => 'varchar', 'length' => 8, 'not null' => true, 'description' => 'address type ("email", "xmpp", "sms")'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
				
			||||||
                'registered_user_id' => array('type' => 'int', 'not null' => false, 'description' => 'if the invitation is converted, who the new user is'),
 | 
					                'registered_user_id' => array('type' => 'int', 'not null' => false, 'description' => 'if the invitation is converted, who the new user is'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ class Location_namespace extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $__table = 'location_namespace';              // table name
 | 
					    public $__table = 'location_namespace';              // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $description;                     // varchar(255)
 | 
					    public $description;                     // varchar(191)
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +44,7 @@ class Location_namespace extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'identity for this namespace'),
 | 
					                'id' => array('type' => 'int', 'not null' => true, 'description' => 'identity for this namespace'),
 | 
				
			||||||
                'description' => array('type' => 'varchar', 'length' => 255, 'description' => 'description of the namespace'),
 | 
					                'description' => array('type' => 'varchar', 'length' => 191, 'description' => 'description of the namespace'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the record was created'),
 | 
					                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the record was created'),
 | 
				
			||||||
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -299,6 +299,11 @@ abstract class Managed_DataObject extends Memcached_DataObject
 | 
				
			|||||||
        return $ckeys;
 | 
					        return $ckeys;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function escapedTableName()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return common_database_tablename($this->tableName());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns an ID, checked that it is set and reasonably valid
 | 
					     * Returns an ID, checked that it is set and reasonably valid
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -391,4 +396,9 @@ abstract class Managed_DataObject extends Memcached_DataObject
 | 
				
			|||||||
        // @FIXME return true only if something changed (otherwise 0)
 | 
					        // @FIXME return true only if something changed (otherwise 0)
 | 
				
			||||||
        return $result;
 | 
					        return $result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static public function beforeSchemaUpdate()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // NOOP
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -734,7 +734,7 @@ class Memcached_DataObject extends Safe_DataObject
 | 
				
			|||||||
        return $string;
 | 
					        return $string;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We overload so that 'SET NAMES "utf8"' is called for
 | 
					    // We overload so that 'SET NAMES "utf8mb4"' is called for
 | 
				
			||||||
    // each connection
 | 
					    // each connection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function _connect()
 | 
					    function _connect()
 | 
				
			||||||
@@ -784,9 +784,9 @@ class Memcached_DataObject extends Safe_DataObject
 | 
				
			|||||||
                $conn = $DB->connection;
 | 
					                $conn = $DB->connection;
 | 
				
			||||||
                if (!empty($conn)) {
 | 
					                if (!empty($conn)) {
 | 
				
			||||||
                    if ($DB instanceof DB_mysqli || $DB instanceof MDB2_Driver_mysqli) {
 | 
					                    if ($DB instanceof DB_mysqli || $DB instanceof MDB2_Driver_mysqli) {
 | 
				
			||||||
                        mysqli_set_charset($conn, 'utf8');
 | 
					                        mysqli_set_charset($conn, 'utf8mb4');
 | 
				
			||||||
                    } else if ($DB instanceof DB_mysql || $DB instanceof MDB2_Driver_mysql) {
 | 
					                    } else if ($DB instanceof DB_mysql || $DB instanceof MDB2_Driver_mysql) {
 | 
				
			||||||
                        mysql_set_charset('utf8', $conn);
 | 
					                        mysql_set_charset('utf8mb4', $conn);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ class Nonce extends Managed_DataObject
 | 
				
			|||||||
    /* the code below is auto generated do not remove the above tag */
 | 
					    /* the code below is auto generated do not remove the above tag */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $__table = 'nonce';                           // table name
 | 
					    public $__table = 'nonce';                           // table name
 | 
				
			||||||
    public $consumer_key;                    // varchar(255)  primary_key not_null
 | 
					    public $consumer_key;                    // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $tok;                             // char(32)
 | 
					    public $tok;                             // char(32)
 | 
				
			||||||
    public $nonce;                           // char(32)  primary_key not_null
 | 
					    public $nonce;                           // char(32)  primary_key not_null
 | 
				
			||||||
    public $ts;                              // datetime()  primary_key not_null
 | 
					    public $ts;                              // datetime()  primary_key not_null
 | 
				
			||||||
@@ -39,7 +39,7 @@ class Nonce extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'description' => 'OAuth nonce record',
 | 
					            'description' => 'OAuth nonce record',
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'consumer_key' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
					                'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
				
			||||||
                'tok' => array('type' => 'char', 'length' => 32, 'description' => 'buggy old value, ignored'),
 | 
					                'tok' => array('type' => 'char', 'length' => 32, 'description' => 'buggy old value, ignored'),
 | 
				
			||||||
                'nonce' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'nonce'),
 | 
					                'nonce' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'nonce'),
 | 
				
			||||||
                'ts' => array('type' => 'datetime', 'not null' => true, 'description' => 'timestamp sent'),
 | 
					                'ts' => array('type' => 'datetime', 'not null' => true, 'description' => 'timestamp sent'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,10 +55,10 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'notice';                          // table name
 | 
					    public $__table = 'notice';                          // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $profile_id;                      // int(4)  multiple_key not_null
 | 
					    public $profile_id;                      // int(4)  multiple_key not_null
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $content;                         // text
 | 
					    public $content;                         // text
 | 
				
			||||||
    public $rendered;                        // text
 | 
					    public $rendered;                        // text
 | 
				
			||||||
    public $url;                             // varchar(255)
 | 
					    public $url;                             // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime  multiple_key not_null default_0000-00-00%2000%3A00%3A00
 | 
					    public $created;                         // datetime  multiple_key not_null default_0000-00-00%2000%3A00%3A00
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
    public $reply_to;                        // int(4)
 | 
					    public $reply_to;                        // int(4)
 | 
				
			||||||
@@ -70,8 +70,8 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
    public $location_id;                     // int(4)
 | 
					    public $location_id;                     // int(4)
 | 
				
			||||||
    public $location_ns;                     // int(4)
 | 
					    public $location_ns;                     // int(4)
 | 
				
			||||||
    public $repeat_of;                       // int(4)
 | 
					    public $repeat_of;                       // int(4)
 | 
				
			||||||
    public $verb;                            // varchar(255)
 | 
					    public $verb;                            // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $object_type;                     // varchar(255)
 | 
					    public $object_type;                     // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $scope;                           // int(4)
 | 
					    public $scope;                           // int(4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* the code above is auto generated do not remove the tag below */
 | 
					    /* the code above is auto generated do not remove the tag below */
 | 
				
			||||||
@@ -83,10 +83,10 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
					                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
				
			||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'who made the update'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'who made the update'),
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'),
 | 
				
			||||||
                'content' => array('type' => 'text', 'description' => 'update content', 'collate' => 'utf8_general_ci'),
 | 
					                'content' => array('type' => 'text', 'description' => 'update content', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'),
 | 
					                'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'),
 | 
				
			||||||
                'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'),
 | 
					                'url' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
                'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'),
 | 
					                'reply_to' => array('type' => 'int', 'description' => 'notice replied to (usually a guess)'),
 | 
				
			||||||
@@ -98,8 +98,8 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
                'location_id' => array('type' => 'int', 'description' => 'location id if possible'),
 | 
					                'location_id' => array('type' => 'int', 'description' => 'location id if possible'),
 | 
				
			||||||
                'location_ns' => array('type' => 'int', 'description' => 'namespace for location'),
 | 
					                'location_ns' => array('type' => 'int', 'description' => 'namespace for location'),
 | 
				
			||||||
                'repeat_of' => array('type' => 'int', 'description' => 'notice this is a repeat of'),
 | 
					                'repeat_of' => array('type' => 'int', 'description' => 'notice this is a repeat of'),
 | 
				
			||||||
                'object_type' => array('type' => 'varchar', 'length' => 255, 'description' => 'URI representing activity streams object type', 'default' => 'http://activitystrea.ms/schema/1.0/note'),
 | 
					                'object_type' => array('type' => 'varchar', 'length' => 191, 'description' => 'URI representing activity streams object type', 'default' => 'http://activitystrea.ms/schema/1.0/note'),
 | 
				
			||||||
                'verb' => array('type' => 'varchar', 'length' => 255, 'description' => 'URI representing activity streams verb', 'default' => 'http://activitystrea.ms/schema/1.0/post'),
 | 
					                'verb' => array('type' => 'varchar', 'length' => 191, 'description' => 'URI representing activity streams verb', 'default' => 'http://activitystrea.ms/schema/1.0/post'),
 | 
				
			||||||
                'scope' => array('type' => 'int',
 | 
					                'scope' => array('type' => 'int',
 | 
				
			||||||
                                 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = followers; null = default'),
 | 
					                                 'description' => 'bit map for distribution scope; 0 = everywhere; 1 = this server only; 2 = addressees; 4 = followers; null = default'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@@ -313,6 +313,16 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
        return $notice;
 | 
					        return $notice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static function getById($id)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $notice = new Notice();
 | 
				
			||||||
 | 
					        $notice->id = $id;
 | 
				
			||||||
 | 
					        if (!$notice->find(true)) {
 | 
				
			||||||
 | 
					            throw new NoResultException($notice);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $notice;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Extract #hashtags from this notice's content and save them to the database.
 | 
					     * Extract #hashtags from this notice's content and save them to the database.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -892,6 +902,12 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
                $stored->insert();    // throws exception on error
 | 
					                $stored->insert();    // throws exception on error
 | 
				
			||||||
                $orig = clone($stored); // for updating later in this try clause
 | 
					                $orig = clone($stored); // for updating later in this try clause
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $object = null;
 | 
				
			||||||
 | 
					                Event::handle('StoreActivityObject', array($act, $stored, $options, &$object));
 | 
				
			||||||
 | 
					                if (empty($object)) {
 | 
				
			||||||
 | 
					                    throw new ServerException('Unsuccessful call to StoreActivityObject '.$stored->uri . ': '.$act->asString());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // If it's not part of a conversation, it's
 | 
					                // If it's not part of a conversation, it's
 | 
				
			||||||
                // the beginning of a new conversation.
 | 
					                // the beginning of a new conversation.
 | 
				
			||||||
                if (empty($stored->conversation)) {
 | 
					                if (empty($stored->conversation)) {
 | 
				
			||||||
@@ -900,12 +916,6 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
                    $stored->conversation = $conv->id;
 | 
					                    $stored->conversation = $conv->id;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $object = null;
 | 
					 | 
				
			||||||
                Event::handle('StoreActivityObject', array($act, $stored, $options, &$object));
 | 
					 | 
				
			||||||
                if (empty($object)) {
 | 
					 | 
				
			||||||
                    throw new ServerException('No object from StoreActivityObject '.$stored->uri . ': '.$act->asString());
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                $stored->object_type = ActivityUtils::resolveUri($object->getObjectType(), true);
 | 
					 | 
				
			||||||
                $stored->update($orig);
 | 
					                $stored->update($orig);
 | 
				
			||||||
            } catch (Exception $e) {
 | 
					            } catch (Exception $e) {
 | 
				
			||||||
                if (empty($stored->id)) {
 | 
					                if (empty($stored->id)) {
 | 
				
			||||||
@@ -1067,13 +1077,9 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $args = func_get_args();
 | 
					        $args = func_get_args();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $format = array_shift($args);
 | 
					        $format = array_shift($args);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $keyPart = vsprintf($format, $args);
 | 
					        $keyPart = vsprintf($format, $args);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $cacheKey = Cache::key($keyPart);
 | 
					        $cacheKey = Cache::key($keyPart);
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        $c->delete($cacheKey);
 | 
					        $c->delete($cacheKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // delete the "last" stream, too, if this notice is
 | 
					        // delete the "last" stream, too, if this notice is
 | 
				
			||||||
@@ -1194,17 +1200,13 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $f2ps = File_to_post::listGet('post_id', array($this->id));
 | 
					        $f2ps = File_to_post::listGet('post_id', array($this->id));
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		$ids = array();
 | 
							$ids = array();
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		foreach ($f2ps[$this->id] as $f2p) {
 | 
							foreach ($f2ps[$this->id] as $f2p) {
 | 
				
			||||||
            $ids[] = $f2p->file_id;
 | 
					            $ids[] = $f2p->file_id;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$files = File::multiGet('id', $ids);
 | 
							$files = File::multiGet('id', $ids);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		$this->_attachments[$this->id] = $files->fetchAll();
 | 
							$this->_attachments[$this->id] = $files->fetchAll();
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
        return $this->_attachments[$this->id];
 | 
					        return $this->_attachments[$this->id];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1766,15 +1768,12 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $ids = array();
 | 
					        $ids = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		foreach ($gis[$this->id] as $gi)
 | 
							foreach ($gis[$this->id] as $gi) {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		    $ids[] = $gi->group_id;
 | 
							    $ids[] = $gi->group_id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$groups = User_group::multiGet('id', $ids);
 | 
							$groups = User_group::multiGet('id', $ids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		$this->_groups[$this->id] = $groups->fetchAll();
 | 
							$this->_groups[$this->id] = $groups->fetchAll();
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		return $this->_groups[$this->id];
 | 
							return $this->_groups[$this->id];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1819,17 +1818,7 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            $act->verb = $this->verb;
 | 
					            $act->verb = $this->verb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->repeat_of) {
 | 
					            if (!$this->repeat_of) {
 | 
				
			||||||
                $repeated = Notice::getKV('id', $this->repeat_of);
 | 
					 | 
				
			||||||
                if ($repeated instanceof Notice) {
 | 
					 | 
				
			||||||
                    // TRANS: A repeat activity's title. %1$s is repeater's nickname
 | 
					 | 
				
			||||||
                    //        and %2$s is the repeated user's nickname.
 | 
					 | 
				
			||||||
                    $act->title = sprintf(_('%1$s repeated a notice by %2$s'),
 | 
					 | 
				
			||||||
                                          $this->getProfile()->getNickname(),
 | 
					 | 
				
			||||||
                                          $repeated->getProfile()->getNickname());
 | 
					 | 
				
			||||||
                    $act->objects[] = $repeated->asActivity($scoped);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                $act->objects[] = $this->asActivityObject();
 | 
					                $act->objects[] = $this->asActivityObject();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2687,34 +2676,26 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
            $scope = self::defaultScope();
 | 
					            $scope = self::defaultScope();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If there's no scope, anyone (even anon) is in scope.
 | 
					        if ($scope == 0 && !$this->getProfile()->isPrivateStream()) { // Not scoping, so it is public.
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($scope == 0) { // Not private
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return !$this->isHiddenSpam($profile);
 | 
					            return !$this->isHiddenSpam($profile);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        } else { // Private, somehow
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // If there's scope, anon cannot be in scope
 | 
					        // If there's scope, anon cannot be in scope
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (empty($profile)) {
 | 
					        if (empty($profile)) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Author is always in scope
 | 
					        // Author is always in scope
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->profile_id == $profile->id) {
 | 
					        if ($this->profile_id == $profile->id) {
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Only for users on this site
 | 
					        // Only for users on this site
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (($scope & Notice::SITE_SCOPE) && !$profile->isLocal()) {
 | 
					        if (($scope & Notice::SITE_SCOPE) && !$profile->isLocal()) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Only for users mentioned in the notice
 | 
					        // Only for users mentioned in the notice
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($scope & Notice::ADDRESSEE_SCOPE) {
 | 
					        if ($scope & Notice::ADDRESSEE_SCOPE) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $reply = Reply::pkeyGet(array('notice_id' => $this->id,
 | 
					            $reply = Reply::pkeyGet(array('notice_id' => $this->id,
 | 
				
			||||||
@@ -2726,7 +2707,6 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Only for members of the given group
 | 
					        // Only for members of the given group
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($scope & Notice::GROUP_SCOPE) {
 | 
					        if ($scope & Notice::GROUP_SCOPE) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // XXX: just query for the single membership
 | 
					            // XXX: just query for the single membership
 | 
				
			||||||
@@ -2747,26 +2727,15 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Only for followers of the author
 | 
					        if ($scope & Notice::FOLLOWER_SCOPE || $this->getProfile()->isPrivateStream()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $author = null;
 | 
					            if (!Subscription::exists($profile, $this->getProfile())) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($scope & Notice::FOLLOWER_SCOPE) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                try {
 | 
					 | 
				
			||||||
                    $author = $this->getProfile();
 | 
					 | 
				
			||||||
                } catch (Exception $e) {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
                if (!Subscription::exists($profile, $author)) {
 | 
					 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return !$this->isHiddenSpam($profile);
 | 
					        return !$this->isHiddenSpam($profile);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function isHiddenSpam($profile) {
 | 
					    function isHiddenSpam($profile) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2836,7 +2805,6 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
	static function fillProfiles($notices)
 | 
						static function fillProfiles($notices)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$map = self::getProfiles($notices);
 | 
							$map = self::getProfiles($notices);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		foreach ($notices as $entry=>$notice) {
 | 
							foreach ($notices as $entry=>$notice) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
    			if (array_key_exists($notice->profile_id, $map)) {
 | 
					    			if (array_key_exists($notice->profile_id, $map)) {
 | 
				
			||||||
@@ -2857,22 +2825,17 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
		foreach ($notices as $notice) {
 | 
							foreach ($notices as $notice) {
 | 
				
			||||||
			$ids[] = $notice->profile_id;
 | 
								$ids[] = $notice->profile_id;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		$ids = array_unique($ids);
 | 
							$ids = array_unique($ids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		return Profile::pivotGet('id', $ids);
 | 
							return Profile::pivotGet('id', $ids);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static function fillGroups(&$notices)
 | 
						static function fillGroups(&$notices)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
        $ids = self::_idsOf($notices);
 | 
					        $ids = self::_idsOf($notices);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
        $gis = Group_inbox::listGet('notice_id', $ids);
 | 
					        $gis = Group_inbox::listGet('notice_id', $ids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
        $gids = array();
 | 
					        $gids = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		foreach ($gis as $id => $gi)
 | 
							foreach ($gis as $id => $gi) {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		    foreach ($gi as $g)
 | 
							    foreach ($gi as $g)
 | 
				
			||||||
		    {
 | 
							    {
 | 
				
			||||||
		        $gids[] = $g->group_id;
 | 
							        $gids[] = $g->group_id;
 | 
				
			||||||
@@ -2880,9 +2843,7 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$gids = array_unique($gids);
 | 
							$gids = array_unique($gids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		$group = User_group::pivotGet('id', $gids);
 | 
							$group = User_group::pivotGet('id', $gids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		foreach ($notices as $notice)
 | 
							foreach ($notices as $notice)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			$grps = array();
 | 
								$grps = array();
 | 
				
			||||||
@@ -2906,11 +2867,8 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
    static function fillAttachments(&$notices)
 | 
					    static function fillAttachments(&$notices)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $ids = self::_idsOf($notices);
 | 
					        $ids = self::_idsOf($notices);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $f2pMap = File_to_post::listGet('post_id', $ids);
 | 
					        $f2pMap = File_to_post::listGet('post_id', $ids);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		$fileIds = array();
 | 
							$fileIds = array();
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		foreach ($f2pMap as $noticeId => $f2ps) {
 | 
							foreach ($f2pMap as $noticeId => $f2ps) {
 | 
				
			||||||
            foreach ($f2ps as $f2p) {
 | 
					            foreach ($f2ps as $f2p) {
 | 
				
			||||||
                $fileIds[] = $f2p->file_id;
 | 
					                $fileIds[] = $f2p->file_id;
 | 
				
			||||||
@@ -2918,9 +2876,7 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $fileIds = array_unique($fileIds);
 | 
					        $fileIds = array_unique($fileIds);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		$fileMap = File::pivotGet('id', $fileIds);
 | 
							$fileMap = File::pivotGet('id', $fileIds);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		foreach ($notices as $notice)
 | 
							foreach ($notices as $notice)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			$files = array();
 | 
								$files = array();
 | 
				
			||||||
@@ -2945,31 +2901,4 @@ class Notice extends Managed_DataObject
 | 
				
			|||||||
            $notice->_setReplies($ids);
 | 
					            $notice->_setReplies($ids);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected $_repeats = array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function getRepeats()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (isset($this->_repeats[$this->id])) {
 | 
					 | 
				
			||||||
            return $this->_repeats[$this->id];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $repeatMap = Notice::listGet('repeat_of', array($this->id));
 | 
					 | 
				
			||||||
        $this->_repeats[$this->id] = $repeatMap[$this->id];
 | 
					 | 
				
			||||||
        return $this->_repeats[$this->id];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function _setRepeats($repeats)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->_repeats[$this->id] = $repeats;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static function fillRepeats(&$notices)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $ids = self::_idsOf($notices);
 | 
					 | 
				
			||||||
        $repeatMap = Notice::listGet('repeat_of', $ids);
 | 
					 | 
				
			||||||
        foreach ($notices as $notice) {
 | 
					 | 
				
			||||||
        	$repeats = $repeatMap[$notice->id];
 | 
					 | 
				
			||||||
            $notice->_setRepeats($repeats);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,8 @@ class Notice_source extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $__table = 'notice_source';                   // table name
 | 
					    public $__table = 'notice_source';                   // table name
 | 
				
			||||||
    public $code;                            // varchar(32)  primary_key not_null
 | 
					    public $code;                            // varchar(32)  primary_key not_null
 | 
				
			||||||
    public $name;                            // varchar(255)   not_null
 | 
					    public $name;                            // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $url;                             // varchar(255)   not_null
 | 
					    public $url;                             // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,8 +24,8 @@ class Notice_source extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'source code'),
 | 
					                'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'source code'),
 | 
				
			||||||
                'name' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'name of the source'),
 | 
					                'name' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'name of the source'),
 | 
				
			||||||
                'url' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'url to link to'),
 | 
					                'url' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'url to link to'),
 | 
				
			||||||
                'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'date this record was created'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,14 +12,14 @@ class Oauth_application extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'oauth_application';               // table name
 | 
					    public $__table = 'oauth_application';               // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $owner;                           // int(4)   not_null
 | 
					    public $owner;                           // int(4)   not_null
 | 
				
			||||||
    public $consumer_key;                    // varchar(255)   not_null
 | 
					    public $consumer_key;                    // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $name;                            // varchar(255)   not_null
 | 
					    public $name;                            // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $description;                     // varchar(255)
 | 
					    public $description;                     // varchar(191)              not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $icon;                            // varchar(255)   not_null
 | 
					    public $icon;                            // varchar(191)              not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $source_url;                      // varchar(255)
 | 
					    public $source_url;                      // varchar(191)              not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $organization;                    // varchar(255)
 | 
					    public $organization;                    // varchar(191)              not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $homepage;                        // varchar(255)
 | 
					    public $homepage;                        // varchar(191)              not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $callback_url;                    // varchar(255)   not_null
 | 
					    public $callback_url;                    // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $type;                            // tinyint(1)
 | 
					    public $type;                            // tinyint(1)
 | 
				
			||||||
    public $access_type;                     // tinyint(1)
 | 
					    public $access_type;                     // tinyint(1)
 | 
				
			||||||
    public $created;                         // datetime   not_null
 | 
					    public $created;                         // datetime   not_null
 | 
				
			||||||
@@ -43,12 +43,12 @@ class Oauth_application extends Managed_DataObject
 | 
				
			|||||||
    static function maxDesc()
 | 
					    static function maxDesc()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // This used to default to textlimit or allow unlimited descriptions,
 | 
					        // This used to default to textlimit or allow unlimited descriptions,
 | 
				
			||||||
        // but this isn't part of a notice and the field's limited to 255 chars
 | 
					        // but this isn't part of a notice and the field's limited to 191 chars
 | 
				
			||||||
        // in the DB, so those seem silly.
 | 
					        // in the DB, so those seem silly. (utf8mb4 takes up more space, so can't use 255)
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        // Now just defaulting to 255 max unless a smaller application desclimit
 | 
					        // Now just defaulting to 191 max unless a smaller application desclimit
 | 
				
			||||||
        // is actually set. Setting to 0 will use the maximum.
 | 
					        // is actually set. Setting to 0 will use the maximum.
 | 
				
			||||||
        $max = 255;
 | 
					        $max = 191;
 | 
				
			||||||
        $desclimit = intval(common_config('application', 'desclimit'));
 | 
					        $desclimit = intval(common_config('application', 'desclimit'));
 | 
				
			||||||
        if ($desclimit > 0 && $desclimit < $max) {
 | 
					        if ($desclimit > 0 && $desclimit < $max) {
 | 
				
			||||||
            return $desclimit;
 | 
					            return $desclimit;
 | 
				
			||||||
@@ -80,7 +80,7 @@ class Oauth_application extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function setOriginal($filename)
 | 
					    function setOriginal($filename)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $imagefile = new ImageFile($this->id, Avatar::path($filename));
 | 
					        $imagefile = new ImageFile(null, Avatar::path($filename));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // XXX: Do we want to have a bunch of different size icons? homepage, stream, mini?
 | 
					        // XXX: Do we want to have a bunch of different size icons? homepage, stream, mini?
 | 
				
			||||||
        // or just one and control size via CSS? --Zach
 | 
					        // or just one and control size via CSS? --Zach
 | 
				
			||||||
@@ -163,14 +163,14 @@ class Oauth_application extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
					                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
				
			||||||
                'owner' => array('type' => 'int', 'not null' => true, 'description' => 'owner of the application'),
 | 
					                'owner' => array('type' => 'int', 'not null' => true, 'description' => 'owner of the application'),
 | 
				
			||||||
                'consumer_key' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'application consumer key'),
 | 
					                'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'application consumer key'),
 | 
				
			||||||
                'name' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'name of the application'),
 | 
					                'name' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'name of the application'),
 | 
				
			||||||
                'description' => array('type' => 'varchar', 'length' => 255, 'description' => 'description of the application'),
 | 
					                'description' => array('type' => 'varchar', 'length' => 191, 'description' => 'description of the application'),
 | 
				
			||||||
                'icon' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'application icon'),
 | 
					                'icon' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'application icon'),
 | 
				
			||||||
                'source_url' => array('type' => 'varchar', 'length' => 255, 'description' => 'application homepage - used for source link'),
 | 
					                'source_url' => array('type' => 'varchar', 'length' => 191, 'description' => 'application homepage - used for source link'),
 | 
				
			||||||
                'organization' => array('type' => 'varchar', 'length' => 255, 'description' => 'name of the organization running the application'),
 | 
					                'organization' => array('type' => 'varchar', 'length' => 191, 'description' => 'name of the organization running the application'),
 | 
				
			||||||
                'homepage' => array('type' => 'varchar', 'length' => 255, 'description' => 'homepage for the organization'),
 | 
					                'homepage' => array('type' => 'varchar', 'length' => 191, 'description' => 'homepage for the organization'),
 | 
				
			||||||
                'callback_url' => array('type' => 'varchar', 'length' => 255, 'description' => 'url to redirect to after authentication'),
 | 
					                'callback_url' => array('type' => 'varchar', 'length' => 191, 'description' => 'url to redirect to after authentication'),
 | 
				
			||||||
                'type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'type of app, 1 = browser, 2 = desktop'),
 | 
					                'type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'type of app, 1 = browser, 2 = desktop'),
 | 
				
			||||||
                'access_type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'default access type, bit 1 = read, bit 2 = write'),
 | 
					                'access_type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'default access type, bit 1 = read, bit 2 = write'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ class Oauth_application_user extends Managed_DataObject
 | 
				
			|||||||
    public $profile_id;                      // int(4)  primary_key not_null
 | 
					    public $profile_id;                      // int(4)  primary_key not_null
 | 
				
			||||||
    public $application_id;                  // int(4)  primary_key not_null
 | 
					    public $application_id;                  // int(4)  primary_key not_null
 | 
				
			||||||
    public $access_type;                     // tinyint(1)
 | 
					    public $access_type;                     // tinyint(1)
 | 
				
			||||||
    public $token;                           // varchar(255)
 | 
					    public $token;                           // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime   not_null
 | 
					    public $created;                         // datetime   not_null
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,7 +27,7 @@ class Oauth_application_user extends Managed_DataObject
 | 
				
			|||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'user of the application'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'user of the application'),
 | 
				
			||||||
                'application_id' => array('type' => 'int', 'not null' => true, 'description' => 'id of the application'),
 | 
					                'application_id' => array('type' => 'int', 'not null' => true, 'description' => 'id of the application'),
 | 
				
			||||||
                'access_type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'access type, bit 1 = read, bit 2 = write'),
 | 
					                'access_type' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'access type, bit 1 = read, bit 2 = write'),
 | 
				
			||||||
                'token' => array('type' => 'varchar', 'length' => 255, 'description' => 'request or access token'),
 | 
					                'token' => array('type' => 'varchar', 'length' => 191, 'description' => 'request or access token'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Oauth_token_association extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'oauth_token_association';          // table name
 | 
					    public $__table = 'oauth_token_association';          // table name
 | 
				
			||||||
    public $profile_id;                      // int(4)  primary_key not_null
 | 
					    public $profile_id;                      // int(4)  primary_key not_null
 | 
				
			||||||
    public $application_id;                  // int(4)  primary_key not_null
 | 
					    public $application_id;                  // int(4)  primary_key not_null
 | 
				
			||||||
    public $token;                           // varchar(255) primary key not null
 | 
					    public $token;                           // varchar(191) primary key not null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime   not_null
 | 
					    public $created;                         // datetime   not_null
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,7 +43,7 @@ class Oauth_token_association extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'associated user'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'associated user'),
 | 
				
			||||||
                'application_id' => array('type' => 'int', 'not null' => true, 'description' => 'the application'),
 | 
					                'application_id' => array('type' => 'int', 'not null' => true, 'description' => 'the application'),
 | 
				
			||||||
                'token' => array('type' => 'varchar', 'length' => '255', 'not null' => true, 'description' => 'token used for this association'),
 | 
					                'token' => array('type' => 'varchar', 'length' => '191', 'not null' => true, 'description' => 'token used for this association'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,11 +30,11 @@ class Profile extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'profile';                         // table name
 | 
					    public $__table = 'profile';                         // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $nickname;                        // varchar(64)  multiple_key not_null
 | 
					    public $nickname;                        // varchar(64)  multiple_key not_null
 | 
				
			||||||
    public $fullname;                        // varchar(255)  multiple_key
 | 
					    public $fullname;                        // varchar(191)  multiple_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $profileurl;                      // varchar(255)
 | 
					    public $profileurl;                      // varchar(191)                 not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $homepage;                        // varchar(255)  multiple_key
 | 
					    public $homepage;                        // varchar(191)  multiple_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $bio;                             // text()  multiple_key
 | 
					    public $bio;                             // text()  multiple_key
 | 
				
			||||||
    public $location;                        // varchar(255)  multiple_key
 | 
					    public $location;                        // varchar(191)  multiple_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $lat;                             // decimal(10,7)
 | 
					    public $lat;                             // decimal(10,7)
 | 
				
			||||||
    public $lon;                             // decimal(10,7)
 | 
					    public $lon;                             // decimal(10,7)
 | 
				
			||||||
    public $location_id;                     // int(4)
 | 
					    public $location_id;                     // int(4)
 | 
				
			||||||
@@ -49,11 +49,11 @@ class Profile extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
					                'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
 | 
				
			||||||
                'nickname' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'nickname or username', 'collate' => 'utf8_general_ci'),
 | 
					                'nickname' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'nickname or username', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'fullname' => array('type' => 'varchar', 'length' => 255, 'description' => 'display name', 'collate' => 'utf8_general_ci'),
 | 
					                'fullname' => array('type' => 'varchar', 'length' => 191, 'description' => 'display name', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'profileurl' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL, cached so we dont regenerate'),
 | 
					                'profileurl' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL, cached so we dont regenerate'),
 | 
				
			||||||
                'homepage' => array('type' => 'varchar', 'length' => 255, 'description' => 'identifying URL', 'collate' => 'utf8_general_ci'),
 | 
					                'homepage' => array('type' => 'varchar', 'length' => 191, 'description' => 'identifying URL', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'bio' => array('type' => 'text', 'description' => 'descriptive biography', 'collate' => 'utf8_general_ci'),
 | 
					                'bio' => array('type' => 'text', 'description' => 'descriptive biography', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'location' => array('type' => 'varchar', 'length' => 255, 'description' => 'physical location', 'collate' => 'utf8_general_ci'),
 | 
					                'location' => array('type' => 'varchar', 'length' => 191, 'description' => 'physical location', 'collate' => 'utf8_general_ci'),
 | 
				
			||||||
                'lat' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'latitude'),
 | 
					                'lat' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'latitude'),
 | 
				
			||||||
                'lon' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'longitude'),
 | 
					                'lon' => array('type' => 'numeric', 'precision' => 10, 'scale' => 7, 'description' => 'longitude'),
 | 
				
			||||||
                'location_id' => array('type' => 'int', 'description' => 'location id if possible'),
 | 
					                'location_id' => array('type' => 'int', 'description' => 'location id if possible'),
 | 
				
			||||||
@@ -160,7 +160,7 @@ class Profile extends Managed_DataObject
 | 
				
			|||||||
            return $this->getGroup()->setOriginal($filename);
 | 
					            return $this->getGroup()->setOriginal($filename);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $imagefile = new ImageFile($this->id, Avatar::path($filename));
 | 
					        $imagefile = new ImageFile(null, Avatar::path($filename));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $avatar = new Avatar();
 | 
					        $avatar = new Avatar();
 | 
				
			||||||
        $avatar->profile_id = $this->id;
 | 
					        $avatar->profile_id = $this->id;
 | 
				
			||||||
@@ -1451,6 +1451,12 @@ class Profile extends Managed_DataObject
 | 
				
			|||||||
        return $feed;
 | 
					        return $feed;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // TRANS: Exception thrown when trying view "repeated to me".
 | 
				
			||||||
 | 
					        throw new Exception(_('Not implemented since inbox change.'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Get a Profile object by URI. Will call external plugins for help
 | 
					     * Get a Profile object by URI. Will call external plugins for help
 | 
				
			||||||
     * using the event StartGetProfileFromURI.
 | 
					     * using the event StartGetProfileFromURI.
 | 
				
			||||||
@@ -1566,6 +1572,15 @@ class Profile extends Managed_DataObject
 | 
				
			|||||||
        return $this->getUser()->shortenLinks($text, $always);
 | 
					        return $this->getUser()->shortenLinks($text, $always);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isPrivateStream()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // We only know of public remote users as of yet...
 | 
				
			||||||
 | 
					        if (!$this->isLocal()) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $this->getUser()->private_stream ? true : false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function delPref($namespace, $topic) {
 | 
					    public function delPref($namespace, $topic) {
 | 
				
			||||||
        return Profile_prefs::setData($this, $namespace, $topic, null);
 | 
					        return Profile_prefs::setData($this, $namespace, $topic, null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,8 +43,8 @@ class Profile_list extends Managed_DataObject
 | 
				
			|||||||
    public $private;                         // tinyint(1)
 | 
					    public $private;                         // tinyint(1)
 | 
				
			||||||
    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
					    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $mainpage;                        // varchar(255)
 | 
					    public $mainpage;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $tagged_count;                    // smallint
 | 
					    public $tagged_count;                    // smallint
 | 
				
			||||||
    public $subscriber_count;                // smallint
 | 
					    public $subscriber_count;                // smallint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,8 +64,8 @@ class Profile_list extends Managed_DataObject
 | 
				
			|||||||
                'created' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was added'),
 | 
					                'created' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was added'),
 | 
				
			||||||
                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was modified'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date the tag was modified'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universal identifier'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
 | 
				
			||||||
                'mainpage' => array('type' => 'varchar', 'length' => 255, 'description' => 'page to link to'),
 | 
					                'mainpage' => array('type' => 'varchar', 'length' => 191, 'description' => 'page to link to'),
 | 
				
			||||||
                'tagged_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of people tagged with this tag by this user'),
 | 
					                'tagged_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of people tagged with this tag by this user'),
 | 
				
			||||||
                'subscriber_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of subscribers to this tag'),
 | 
					                'subscriber_count' => array('type' => 'int', 'default' => 0, 'description' => 'number of subscribers to this tag'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,8 +31,8 @@ class Profile_prefs extends Managed_DataObject
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public $__table = 'profile_prefs';       // table name
 | 
					    public $__table = 'profile_prefs';       // table name
 | 
				
			||||||
    public $profile_id;                      // int(4)  primary_key not_null
 | 
					    public $profile_id;                      // int(4)  primary_key not_null
 | 
				
			||||||
    public $namespace;                       // varchar(255)  not_null
 | 
					    public $namespace;                       // varchar(191)  not_null
 | 
				
			||||||
    public $topic;                           // varchar(255)  not_null
 | 
					    public $topic;                           // varchar(191)  not_null
 | 
				
			||||||
    public $data;                            // text
 | 
					    public $data;                            // text
 | 
				
			||||||
    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
					    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
@@ -42,8 +42,8 @@ class Profile_prefs extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
 | 
				
			||||||
                'namespace' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'namespace, like pluginname or category'),
 | 
					                'namespace' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'namespace, like pluginname or category'),
 | 
				
			||||||
                'topic' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'preference key, i.e. description, age...'),
 | 
					                'topic' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'preference key, i.e. description, age...'),
 | 
				
			||||||
                'data' => array('type' => 'blob', 'description' => 'topic data, may be anything'),
 | 
					                'data' => array('type' => 'blob', 'description' => 'topic data, may be anything'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Sms_carrier extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'sms_carrier';                     // table name
 | 
					    public $__table = 'sms_carrier';                     // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $name;                            // varchar(64)  unique_key
 | 
					    public $name;                            // varchar(64)  unique_key
 | 
				
			||||||
    public $email_pattern;                   // varchar(255)   not_null
 | 
					    public $email_pattern;                   // varchar(191)   not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,7 +30,7 @@ class Sms_carrier extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'primary key for SMS carrier'),
 | 
					                'id' => array('type' => 'int', 'not null' => true, 'description' => 'primary key for SMS carrier'),
 | 
				
			||||||
                'name' => array('type' => 'varchar', 'length' => 64, 'description' => 'name of the carrier'),
 | 
					                'name' => array('type' => 'varchar', 'length' => 64, 'description' => 'name of the carrier'),
 | 
				
			||||||
                'email_pattern' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'sprintf pattern for making an email address from a phone number'),
 | 
					                'email_pattern' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'sprintf pattern for making an email address from a phone number'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,15 +29,15 @@ class Status_network extends Safe_DataObject
 | 
				
			|||||||
    public $__table = 'status_network';                  // table name
 | 
					    public $__table = 'status_network';                  // table name
 | 
				
			||||||
    public $site_id;                         // int(4) primary_key not_null
 | 
					    public $site_id;                         // int(4) primary_key not_null
 | 
				
			||||||
    public $nickname;                        // varchar(64)   unique_key not_null
 | 
					    public $nickname;                        // varchar(64)   unique_key not_null
 | 
				
			||||||
    public $hostname;                        // varchar(255)  unique_key
 | 
					    public $hostname;                        // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $pathname;                        // varchar(255)  unique_key
 | 
					    public $pathname;                        // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $dbhost;                          // varchar(255)
 | 
					    public $dbhost;                          // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $dbuser;                          // varchar(255)
 | 
					    public $dbuser;                          // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $dbpass;                          // varchar(255)
 | 
					    public $dbpass;                          // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $dbname;                          // varchar(255)
 | 
					    public $dbname;                          // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $sitename;                        // varchar(255)
 | 
					    public $sitename;                        // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $theme;                           // varchar(255)
 | 
					    public $theme;                           // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $logo;                            // varchar(255)
 | 
					    public $logo;                            // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,9 +32,9 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
    public $subscribed;                      // int(4)  primary_key not_null
 | 
					    public $subscribed;                      // int(4)  primary_key not_null
 | 
				
			||||||
    public $jabber;                          // tinyint(1)   default_1
 | 
					    public $jabber;                          // tinyint(1)   default_1
 | 
				
			||||||
    public $sms;                             // tinyint(1)   default_1
 | 
					    public $sms;                             // tinyint(1)   default_1
 | 
				
			||||||
    public $token;                           // varchar(255)
 | 
					    public $token;                           // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $secret;                          // varchar(255)
 | 
					    public $secret;                          // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $uri;                             // varchar(255)
 | 
					    public $uri;                             // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,9 +46,9 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
                'subscribed' => array('type' => 'int', 'not null' => true, 'description' => 'profile being listened to'),
 | 
					                'subscribed' => array('type' => 'int', 'not null' => true, 'description' => 'profile being listened to'),
 | 
				
			||||||
                'jabber' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver jabber messages'),
 | 
					                'jabber' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver jabber messages'),
 | 
				
			||||||
                'sms' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver sms messages'),
 | 
					                'sms' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'deliver sms messages'),
 | 
				
			||||||
                'token' => array('type' => 'varchar', 'length' => 255, 'description' => 'authorization token'),
 | 
					                'token' => array('type' => 'varchar', 'length' => 191, 'description' => 'authorization token'),
 | 
				
			||||||
                'secret' => array('type' => 'varchar', 'length' => 255, 'description' => 'token secret'),
 | 
					                'secret' => array('type' => 'varchar', 'length' => 191, 'description' => 'token secret'),
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@@ -94,8 +94,12 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
        if (Event::handle('StartSubscribe', array($subscriber, $other))) {
 | 
					        if (Event::handle('StartSubscribe', array($subscriber, $other))) {
 | 
				
			||||||
            $otherUser = User::getKV('id', $other->id);
 | 
					            $otherUser = User::getKV('id', $other->id);
 | 
				
			||||||
            if ($otherUser instanceof User && $otherUser->subscribe_policy == User::SUBSCRIBE_POLICY_MODERATE && !$force) {
 | 
					            if ($otherUser instanceof User && $otherUser->subscribe_policy == User::SUBSCRIBE_POLICY_MODERATE && !$force) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
                    $sub = Subscription_queue::saveNew($subscriber, $other);
 | 
					                    $sub = Subscription_queue::saveNew($subscriber, $other);
 | 
				
			||||||
                    $sub->notify();
 | 
					                    $sub->notify();
 | 
				
			||||||
 | 
					                } catch (AlreadyFulfilledException $e) {
 | 
				
			||||||
 | 
					                    $sub = Subscription_queue::getSubQueue($subscriber, $other);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $sub = self::saveNew($subscriber->id, $other->id);
 | 
					                $sub = self::saveNew($subscriber->id, $other->id);
 | 
				
			||||||
                $sub->notify();
 | 
					                $sub->notify();
 | 
				
			||||||
@@ -124,7 +128,7 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($sub instanceof Subscription) { // i.e. not SubscriptionQueue
 | 
					            if ($sub instanceof Subscription) { // i.e. not Subscription_queue
 | 
				
			||||||
                Event::handle('EndSubscribe', array($subscriber, $other));
 | 
					                Event::handle('EndSubscribe', array($subscriber, $other));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -132,6 +136,16 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
        return $sub;
 | 
					        return $sub;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static function ensureStart(Profile $subscriber, Profile $other, $force=false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $sub = self::start($subscriber, $other, $force);
 | 
				
			||||||
 | 
					        } catch (AlreadyFulfilledException $e) {
 | 
				
			||||||
 | 
					            return self::getSubscription($subscriber, $other);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $sub;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Low-level subscription save.
 | 
					     * Low-level subscription save.
 | 
				
			||||||
     * Outside callers should use Subscription::start()
 | 
					     * Outside callers should use Subscription::start()
 | 
				
			||||||
@@ -232,9 +246,25 @@ class Subscription extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static function exists(Profile $subscriber, Profile $other)
 | 
					    static function exists(Profile $subscriber, Profile $other)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id,
 | 
					        try {
 | 
				
			||||||
                                           'subscribed' => $other->id));
 | 
					            $sub = self::getSubscription($subscriber, $other);
 | 
				
			||||||
        return ($sub instanceof Subscription);
 | 
					        } catch (NoResultException $e) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static function getSubscription(Profile $subscriber, Profile $other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // This is essentially a pkeyGet but we have an object to return in NoResultException
 | 
				
			||||||
 | 
					        $sub = new Subscription();
 | 
				
			||||||
 | 
					        $sub->subscriber = $subscriber->id;
 | 
				
			||||||
 | 
					        $sub->subscribed = $other->id;
 | 
				
			||||||
 | 
					        if (!$sub->find(true)) {
 | 
				
			||||||
 | 
					            throw new NoResultException($sub);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $sub;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function asActivity()
 | 
					    function asActivity()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,9 @@ class Subscription_queue extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static function saveNew(Profile $subscriber, Profile $subscribed)
 | 
					    public static function saveNew(Profile $subscriber, Profile $subscribed)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        if (self::exists($subscriber, $subscribed)) {
 | 
				
			||||||
 | 
					            throw new AlreadyFulfilledException(_('This subscription request is already in progress.'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        $rq = new Subscription_queue();
 | 
					        $rq = new Subscription_queue();
 | 
				
			||||||
        $rq->subscriber = $subscriber->id;
 | 
					        $rq->subscriber = $subscriber->id;
 | 
				
			||||||
        $rq->subscribed = $subscribed->id;
 | 
					        $rq->subscribed = $subscribed->id;
 | 
				
			||||||
@@ -51,6 +54,18 @@ class Subscription_queue extends Managed_DataObject
 | 
				
			|||||||
        return ($sub instanceof Subscription_queue);
 | 
					        return ($sub instanceof Subscription_queue);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static function getSubQueue(Profile $subscriber, Profile $other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // This is essentially a pkeyGet but we have an object to return in NoResultException
 | 
				
			||||||
 | 
					        $sub = new Subscription_queue();
 | 
				
			||||||
 | 
					        $sub->subscriber = $subscriber->id;
 | 
				
			||||||
 | 
					        $sub->subscribed = $other->id;
 | 
				
			||||||
 | 
					        if (!$sub->find(true)) {
 | 
				
			||||||
 | 
					            throw new NoResultException($sub);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $sub;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Complete a pending subscription, as we've got approval of some sort.
 | 
					     * Complete a pending subscription, as we've got approval of some sort.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,13 +10,13 @@ class Token extends Managed_DataObject
 | 
				
			|||||||
    /* the code below is auto generated do not remove the above tag */
 | 
					    /* the code below is auto generated do not remove the above tag */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $__table = 'token';                           // table name
 | 
					    public $__table = 'token';                           // table name
 | 
				
			||||||
    public $consumer_key;                    // varchar(255)  primary_key not_null
 | 
					    public $consumer_key;                    // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $tok;                             // char(32)  primary_key not_null
 | 
					    public $tok;                             // char(32)  primary_key not_null
 | 
				
			||||||
    public $secret;                          // char(32)   not_null
 | 
					    public $secret;                          // char(32)   not_null
 | 
				
			||||||
    public $type;                            // tinyint(1)   not_null
 | 
					    public $type;                            // tinyint(1)   not_null
 | 
				
			||||||
    public $state;                           // tinyint(1)
 | 
					    public $state;                           // tinyint(1)
 | 
				
			||||||
    public $verifier;                        // varchar(255)
 | 
					    public $verifier;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $verified_callback;               // varchar(255)
 | 
					    public $verified_callback;               // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime()   not_null
 | 
					    public $created;                         // datetime()   not_null
 | 
				
			||||||
    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -27,13 +27,13 @@ class Token extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'description' => 'OAuth token record',
 | 
					            'description' => 'OAuth token record',
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'consumer_key' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
					                'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'unique identifier, root URL'),
 | 
				
			||||||
                'tok' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'identifying value'),
 | 
					                'tok' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'identifying value'),
 | 
				
			||||||
                'secret' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'secret value'),
 | 
					                'secret' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'secret value'),
 | 
				
			||||||
                'type' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'request or access'),
 | 
					                'type' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'request or access'),
 | 
				
			||||||
                'state' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'for requests, 0 = initial, 1 = authorized, 2 = used'),
 | 
					                'state' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'for requests, 0 = initial, 1 = authorized, 2 = used'),
 | 
				
			||||||
                'verifier' => array('type' => 'varchar', 'length' => 255, 'description' => 'verifier string for OAuth 1.0a'),
 | 
					                'verifier' => array('type' => 'varchar', 'length' => 191, 'description' => 'verifier string for OAuth 1.0a'),
 | 
				
			||||||
                'verified_callback' => array('type' => 'varchar', 'length' => 255, 'description' => 'verified callback URL for OAuth 1.0a'),
 | 
					                'verified_callback' => array('type' => 'varchar', 'length' => 191, 'description' => 'verified callback URL for OAuth 1.0a'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,9 +34,9 @@ class User extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'user';                            // table name
 | 
					    public $__table = 'user';                            // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $nickname;                        // varchar(64)  unique_key
 | 
					    public $nickname;                        // varchar(64)  unique_key
 | 
				
			||||||
    public $password;                        // varchar(255)
 | 
					    public $password;                        // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $email;                           // varchar(255)  unique_key
 | 
					    public $email;                           // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $incomingemail;                   // varchar(255)  unique_key
 | 
					    public $incomingemail;                   // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $emailnotifysub;                  // tinyint(1)   default_1
 | 
					    public $emailnotifysub;                  // tinyint(1)   default_1
 | 
				
			||||||
    public $emailnotifyfav;                  // tinyint(1)   default_1
 | 
					    public $emailnotifyfav;                  // tinyint(1)   default_1
 | 
				
			||||||
    public $emailnotifynudge;                // tinyint(1)   default_1
 | 
					    public $emailnotifynudge;                // tinyint(1)   default_1
 | 
				
			||||||
@@ -50,8 +50,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
    public $carrier;                         // int(4)
 | 
					    public $carrier;                         // int(4)
 | 
				
			||||||
    public $smsnotify;                       // tinyint(1)
 | 
					    public $smsnotify;                       // tinyint(1)
 | 
				
			||||||
    public $smsreplies;                      // tinyint(1)
 | 
					    public $smsreplies;                      // tinyint(1)
 | 
				
			||||||
    public $smsemail;                        // varchar(255)
 | 
					    public $smsemail;                        // varchar(191)               not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $autosubscribe;                   // tinyint(1)
 | 
					    public $autosubscribe;                   // tinyint(1)
 | 
				
			||||||
    public $subscribe_policy;                // tinyint(1)
 | 
					    public $subscribe_policy;                // tinyint(1)
 | 
				
			||||||
    public $urlshorteningservice;            // varchar(50)   default_ur1.ca
 | 
					    public $urlshorteningservice;            // varchar(50)   default_ur1.ca
 | 
				
			||||||
@@ -69,9 +69,9 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
					                'id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
				
			||||||
                'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname or username, duped in profile'),
 | 
					                'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname or username, duped in profile'),
 | 
				
			||||||
                'password' => array('type' => 'varchar', 'length' => 255, 'description' => 'salted password, can be null for OpenID users'),
 | 
					                'password' => array('type' => 'varchar', 'length' => 191, 'description' => 'salted password, can be null for OpenID users'),
 | 
				
			||||||
                'email' => array('type' => 'varchar', 'length' => 255, 'description' => 'email address for password recovery etc.'),
 | 
					                'email' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for password recovery etc.'),
 | 
				
			||||||
                'incomingemail' => array('type' => 'varchar', 'length' => 255, 'description' => 'email address for post-by-email'),
 | 
					                'incomingemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'email address for post-by-email'),
 | 
				
			||||||
                'emailnotifysub' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of subscriptions'),
 | 
					                'emailnotifysub' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of subscriptions'),
 | 
				
			||||||
                'emailnotifyfav' => array('type' => 'int', 'size' => 'tiny', 'default' => null, 'description' => 'Notify by email of favorites'),
 | 
					                'emailnotifyfav' => array('type' => 'int', 'size' => 'tiny', 'default' => null, 'description' => 'Notify by email of favorites'),
 | 
				
			||||||
                'emailnotifynudge' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of nudges'),
 | 
					                'emailnotifynudge' => array('type' => 'int', 'size' => 'tiny', 'default' => 1, 'description' => 'Notify by email of nudges'),
 | 
				
			||||||
@@ -85,8 +85,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
                'carrier' => array('type' => 'int', 'description' => 'foreign key to sms_carrier'),
 | 
					                'carrier' => array('type' => 'int', 'description' => 'foreign key to sms_carrier'),
 | 
				
			||||||
                'smsnotify' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS'),
 | 
					                'smsnotify' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS'),
 | 
				
			||||||
                'smsreplies' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS on replies'),
 | 
					                'smsreplies' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'whether to send notices to SMS on replies'),
 | 
				
			||||||
                'smsemail' => array('type' => 'varchar', 'length' => 255, 'description' => 'built from sms and carrier'),
 | 
					                'smsemail' => array('type' => 'varchar', 'length' => 191, 'description' => 'built from sms and carrier'),
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universally unique identifier, usually a tag URI'),
 | 
				
			||||||
                'autosubscribe' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'automatically subscribe to users who subscribe to us'),
 | 
					                'autosubscribe' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => 'automatically subscribe to users who subscribe to us'),
 | 
				
			||||||
                'subscribe_policy' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => '0 = anybody can subscribe; 1 = require approval'),
 | 
					                'subscribe_policy' => array('type' => 'int', 'size' => 'tiny', 'default' => 0, 'description' => '0 = anybody can subscribe; 1 = require approval'),
 | 
				
			||||||
                'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'),
 | 
					                'urlshorteningservice' => array('type' => 'varchar', 'length' => 50, 'default' => 'internal', 'description' => 'service to use for auto-shortening URLs'),
 | 
				
			||||||
@@ -191,7 +191,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
     *              string 'password' (may be missing for eg OpenID registrations)
 | 
					     *              string 'password' (may be missing for eg OpenID registrations)
 | 
				
			||||||
     *              string 'code' invite code
 | 
					     *              string 'code' invite code
 | 
				
			||||||
     *              ?string 'uri' permalink to notice; defaults to local notice URL
 | 
					     *              ?string 'uri' permalink to notice; defaults to local notice URL
 | 
				
			||||||
     * @return mixed User object or false on failure
 | 
					     * @return  User object
 | 
				
			||||||
 | 
					     * @throws  Exception on failure
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static function register(array $fields) {
 | 
					    static function register(array $fields) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -205,12 +206,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            $email = common_canonical_email($email);
 | 
					            $email = common_canonical_email($email);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        // Normalize _and_ check whether it is in use. Throw NicknameException on failure.
 | 
				
			||||||
        $profile->nickname = Nickname::normalize($nickname, true);
 | 
					        $profile->nickname = Nickname::normalize($nickname, true);
 | 
				
			||||||
        } catch (NicknameException $e) {
 | 
					 | 
				
			||||||
            common_log(LOG_WARNING, sprintf('Bad nickname during User registration for %s: %s', $nickname, $e->getMessage()), __FILE__);
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $profile->profileurl = common_profile_url($profile->nickname);
 | 
					        $profile->profileurl = common_profile_url($profile->nickname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -277,7 +274,9 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            $id = $profile->insert();
 | 
					            $id = $profile->insert();
 | 
				
			||||||
            if ($id === false) {
 | 
					            if ($id === false) {
 | 
				
			||||||
                common_log_db_error($profile, 'INSERT', __FILE__);
 | 
					                common_log_db_error($profile, 'INSERT', __FILE__);
 | 
				
			||||||
                return false;
 | 
					                $profile->query('ROLLBACK');
 | 
				
			||||||
 | 
					                // TRANS: Profile data could not be inserted for some reason.
 | 
				
			||||||
 | 
					                throw new ServerException(_m('Could not insert profile data for new user.'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->id = $id;
 | 
					            $user->id = $id;
 | 
				
			||||||
@@ -297,7 +296,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            if ($result === false) {
 | 
					            if ($result === false) {
 | 
				
			||||||
                common_log_db_error($user, 'INSERT', __FILE__);
 | 
					                common_log_db_error($user, 'INSERT', __FILE__);
 | 
				
			||||||
                $profile->query('ROLLBACK');
 | 
					                $profile->query('ROLLBACK');
 | 
				
			||||||
                return false;
 | 
					                // TRANS: User data could not be inserted for some reason.
 | 
				
			||||||
 | 
					                throw new ServerException(_m('Could not insert user data for new user.'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Everyone is subscribed to themself
 | 
					            // Everyone is subscribed to themself
 | 
				
			||||||
@@ -312,7 +312,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            if (!$result) {
 | 
					            if (!$result) {
 | 
				
			||||||
                common_log_db_error($subscription, 'INSERT', __FILE__);
 | 
					                common_log_db_error($subscription, 'INSERT', __FILE__);
 | 
				
			||||||
                $profile->query('ROLLBACK');
 | 
					                $profile->query('ROLLBACK');
 | 
				
			||||||
                return false;
 | 
					                // TRANS: Subscription data could not be inserted for some reason.
 | 
				
			||||||
 | 
					                throw new ServerException(_m('Could not insert subscription data for new user.'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Mark that this invite was converted
 | 
					            // Mark that this invite was converted
 | 
				
			||||||
@@ -334,7 +335,8 @@ class User extends Managed_DataObject
 | 
				
			|||||||
                if (!$result) {
 | 
					                if (!$result) {
 | 
				
			||||||
                    common_log_db_error($confirm, 'INSERT', __FILE__);
 | 
					                    common_log_db_error($confirm, 'INSERT', __FILE__);
 | 
				
			||||||
                    $profile->query('ROLLBACK');
 | 
					                    $profile->query('ROLLBACK');
 | 
				
			||||||
                    return false;
 | 
					                    // TRANS: Email confirmation data could not be inserted for some reason.
 | 
				
			||||||
 | 
					                    throw new ServerException(_m('Could not insert email confirmation data for new user.'));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -352,7 +354,7 @@ class User extends Managed_DataObject
 | 
				
			|||||||
                    common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
 | 
					                    common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
 | 
				
			||||||
                               __FILE__);
 | 
					                               __FILE__);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Subscription::start($profile, $defuser->getProfile());
 | 
					                    Subscription::ensureStart($profile, $defuser->getProfile());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,6 +387,10 @@ class User extends Managed_DataObject
 | 
				
			|||||||
            Event::handle('EndUserRegister', array($profile));
 | 
					            Event::handle('EndUserRegister', array($profile));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!$user instanceof User) {
 | 
				
			||||||
 | 
					            throw new ServerException('User could not be registered. Probably an event hook that failed.');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $user;
 | 
					        return $user;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -687,11 +693,9 @@ class User extends Managed_DataObject
 | 
				
			|||||||
        return $stream->getNotices($offset, $limit, $since_id, $max_id);
 | 
					        return $stream->getNotices($offset, $limit, $since_id, $max_id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
 | 
				
			||||||
    function repeatedToMe($offset=0, $limit=20, $since_id=null, $max_id=null)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TRANS: Exception thrown when trying view "repeated to me".
 | 
					        return $this->getProfile()->repeatedToMe($offset, $limit, $since_id, $max_id);
 | 
				
			||||||
        throw new Exception(_('Not implemented since inbox change.'));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static function siteOwner()
 | 
					    public static function siteOwner()
 | 
				
			||||||
@@ -994,6 +998,11 @@ class User extends Managed_DataObject
 | 
				
			|||||||
        return $act;
 | 
					        return $act;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function isPrivateStream()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->getProfile()->isPrivateStream();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function delPref($namespace, $topic)
 | 
					    public function delPref($namespace, $topic)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->getProfile()->delPref($namespace, $topic);
 | 
					        return $this->getProfile()->delPref($namespace, $topic);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,18 +15,18 @@ class User_group extends Managed_DataObject
 | 
				
			|||||||
    public $__table = 'user_group';                      // table name
 | 
					    public $__table = 'user_group';                      // table name
 | 
				
			||||||
    public $id;                              // int(4)  primary_key not_null
 | 
					    public $id;                              // int(4)  primary_key not_null
 | 
				
			||||||
    public $nickname;                        // varchar(64)
 | 
					    public $nickname;                        // varchar(64)
 | 
				
			||||||
    public $fullname;                        // varchar(255)
 | 
					    public $fullname;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $homepage;                        // varchar(255)
 | 
					    public $homepage;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $description;                     // text
 | 
					    public $description;                     // text
 | 
				
			||||||
    public $location;                        // varchar(255)
 | 
					    public $location;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $original_logo;                   // varchar(255)
 | 
					    public $original_logo;                   // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $homepage_logo;                   // varchar(255)
 | 
					    public $homepage_logo;                   // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $stream_logo;                     // varchar(255)
 | 
					    public $stream_logo;                     // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $mini_logo;                       // varchar(255)
 | 
					    public $mini_logo;                       // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
					    public $created;                         // datetime   not_null default_0000-00-00%2000%3A00%3A00
 | 
				
			||||||
    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                        // timestamp   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
    public $uri;                             // varchar(255)  unique_key
 | 
					    public $uri;                             // varchar(191)  unique_key   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $mainpage;                        // varchar(255)
 | 
					    public $mainpage;                        // varchar(191)   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $join_policy;                     // tinyint
 | 
					    public $join_policy;                     // tinyint
 | 
				
			||||||
    public $force_scope;                     // tinyint
 | 
					    public $force_scope;                     // tinyint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,21 +41,21 @@ class User_group extends Managed_DataObject
 | 
				
			|||||||
                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
					                'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'foreign key to profile table'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname for addressing'),
 | 
					                'nickname' => array('type' => 'varchar', 'length' => 64, 'description' => 'nickname for addressing'),
 | 
				
			||||||
                'fullname' => array('type' => 'varchar', 'length' => 255, 'description' => 'display name'),
 | 
					                'fullname' => array('type' => 'varchar', 'length' => 191, 'description' => 'display name'),
 | 
				
			||||||
                'homepage' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL, cached so we dont regenerate'),
 | 
					                'homepage' => array('type' => 'varchar', 'length' => 191, 'description' => 'URL, cached so we dont regenerate'),
 | 
				
			||||||
                'description' => array('type' => 'text', 'description' => 'group description'),
 | 
					                'description' => array('type' => 'text', 'description' => 'group description'),
 | 
				
			||||||
                'location' => array('type' => 'varchar', 'length' => 255, 'description' => 'related physical location, if any'),
 | 
					                'location' => array('type' => 'varchar', 'length' => 191, 'description' => 'related physical location, if any'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'original_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'original size logo'),
 | 
					                'original_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'original size logo'),
 | 
				
			||||||
                'homepage_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'homepage (profile) size logo'),
 | 
					                'homepage_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'homepage (profile) size logo'),
 | 
				
			||||||
                'stream_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'stream-sized logo'),
 | 
					                'stream_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'stream-sized logo'),
 | 
				
			||||||
                'mini_logo' => array('type' => 'varchar', 'length' => 255, 'description' => 'mini logo'),
 | 
					                'mini_logo' => array('type' => 'varchar', 'length' => 191, 'description' => 'mini logo'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universal identifier'),
 | 
					                'uri' => array('type' => 'varchar', 'length' => 191, 'description' => 'universal identifier'),
 | 
				
			||||||
                'mainpage' => array('type' => 'varchar', 'length' => 255, 'description' => 'page for group info to link to'),
 | 
					                'mainpage' => array('type' => 'varchar', 'length' => 191, 'description' => 'page for group info to link to'),
 | 
				
			||||||
                'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'),      
 | 
					                'join_policy' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=open; 1=requires admin approval'),      
 | 
				
			||||||
                'force_scope' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=never,1=sometimes,-1=always'),
 | 
					                'force_scope' => array('type' => 'int', 'size' => 'tiny', 'description' => '0=never,1=sometimes,-1=always'),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
@@ -312,13 +312,21 @@ class User_group extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function setOriginal($filename)
 | 
					    function setOriginal($filename)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $imagefile = new ImageFile($this->id, Avatar::path($filename));
 | 
					        // This should be handled by the Profile->setOriginal function so user and group avatars are handled the same
 | 
				
			||||||
 | 
					        $imagefile = new ImageFile(null, Avatar::path($filename));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $sizes = array('homepage_logo' => AVATAR_PROFILE_SIZE,
 | 
				
			||||||
 | 
					                       'stream_logo' => AVATAR_STREAM_SIZE,
 | 
				
			||||||
 | 
					                       'mini_logo' => AVATAR_MINI_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $orig = clone($this);
 | 
					        $orig = clone($this);
 | 
				
			||||||
        $this->original_logo = Avatar::url($filename);
 | 
					        $this->original_logo = Avatar::url($filename);
 | 
				
			||||||
        $this->homepage_logo = Avatar::url($imagefile->resize(AVATAR_PROFILE_SIZE));
 | 
					        foreach ($sizes as $name=>$size) {
 | 
				
			||||||
        $this->stream_logo = Avatar::url($imagefile->resize(AVATAR_STREAM_SIZE));
 | 
					            $filename = Avatar::filename($this->profile_id, image_type_to_extension($imagefile->preferredType()),
 | 
				
			||||||
        $this->mini_logo = Avatar::url($imagefile->resize(AVATAR_MINI_SIZE));
 | 
					                                         $size, common_timestamp());
 | 
				
			||||||
 | 
					            $imagefile->resizeTo(Avatar::path($filename), array('width'=>$size, 'height'=>$size));
 | 
				
			||||||
 | 
					            $this->$name = Avatar::url($filename);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        common_debug(common_log_objstring($this));
 | 
					        common_debug(common_log_objstring($this));
 | 
				
			||||||
        return $this->update($orig);
 | 
					        return $this->update($orig);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,8 @@ class User_im_prefs extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $__table = 'user_im_prefs';       // table name
 | 
					    public $__table = 'user_im_prefs';       // table name
 | 
				
			||||||
    public $user_id;                         // int(4)  primary_key not_null
 | 
					    public $user_id;                         // int(4)  primary_key not_null
 | 
				
			||||||
    public $screenname;                      // varchar(255)  not_null
 | 
					    public $screenname;                      // varchar(191)  not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $transport;                       // varchar(255)  not_null
 | 
					    public $transport;                       // varchar(191)  not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $notify;                          // tinyint(1)
 | 
					    public $notify;                          // tinyint(1)
 | 
				
			||||||
    public $replies;                         // tinyint(1)
 | 
					    public $replies;                         // tinyint(1)
 | 
				
			||||||
    public $microid;                         // tinyint(1)
 | 
					    public $microid;                         // tinyint(1)
 | 
				
			||||||
@@ -53,8 +53,8 @@ class User_im_prefs extends Managed_DataObject
 | 
				
			|||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
 | 
					                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user'),
 | 
				
			||||||
                'screenname' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'screenname on this service'),
 | 
					                'screenname' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'screenname on this service'),
 | 
				
			||||||
                'transport' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'transport (ex xmpp, aim)'),
 | 
					                'transport' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'transport (ex xmpp, aim)'),
 | 
				
			||||||
                'notify' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Notify when a new notice is sent'),
 | 
					                'notify' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Notify when a new notice is sent'),
 | 
				
			||||||
                'replies' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies  from people not subscribed to'),
 | 
					                'replies' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 0, 'description' => 'Send replies  from people not subscribed to'),
 | 
				
			||||||
                'microid' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'Publish a MicroID'),
 | 
					                'microid' => array('type' => 'int', 'size' => 'tiny', 'not null' => true, 'default' => 1, 'description' => 'Publish a MicroID'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,8 @@ class User_username extends Managed_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public $__table = 'user_username';                     // table name
 | 
					    public $__table = 'user_username';                     // table name
 | 
				
			||||||
    public $user_id;                        // int(4)  not_null
 | 
					    public $user_id;                        // int(4)  not_null
 | 
				
			||||||
    public $provider_name;                  // varchar(255)  primary_key not_null
 | 
					    public $provider_name;                  // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $username;                       // varchar(255)  primary_key not_null
 | 
					    public $username;                       // varchar(191)  primary_key not_null   not 255 because utf8mb4 takes more space
 | 
				
			||||||
    public $created;                        // datetime()   not_null
 | 
					    public $created;                        // datetime()   not_null
 | 
				
			||||||
    public $modified;                       // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
					    public $modified;                       // timestamp()   not_null default_CURRENT_TIMESTAMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,8 +23,8 @@ class User_username extends Managed_DataObject
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return array(
 | 
					        return array(
 | 
				
			||||||
            'fields' => array(
 | 
					            'fields' => array(
 | 
				
			||||||
                'provider_name' => array('type' => 'varchar', 'length' => 255, 'description' => 'provider name'),
 | 
					                'provider_name' => array('type' => 'varchar', 'length' => 191, 'description' => 'provider name'),
 | 
				
			||||||
                'username' => array('type' => 'varchar', 'length' => 255, 'description' => 'username'),
 | 
					                'username' => array('type' => 'varchar', 'length' => 191, 'description' => 'username'),
 | 
				
			||||||
                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice id this title relates to'),
 | 
					                'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice id this title relates to'),
 | 
				
			||||||
                'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
 | 
					                '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'),
 | 
					                'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,7 @@ create table status_network (
 | 
				
			|||||||
    created datetime not null comment 'date this record was created',
 | 
					    created datetime not null comment 'date this record was created',
 | 
				
			||||||
    modified timestamp comment 'date this record was modified'
 | 
					    modified timestamp comment 'date this record was modified'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
 | 
					) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
create table status_network_tag (
 | 
					create table status_network_tag (
 | 
				
			||||||
    site_id integer  comment 'unique id',
 | 
					    site_id integer  comment 'unique id',
 | 
				
			||||||
@@ -30,5 +30,5 @@ create table status_network_tag (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    constraint primary key (site_id, tag),
 | 
					    constraint primary key (site_id, tag),
 | 
				
			||||||
    index status_network_tag_tag_idx (tag)
 | 
					    index status_network_tag_tag_idx (tag)
 | 
				
			||||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
 | 
					) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,31 @@
 | 
				
			|||||||
 | 
					### GNU social "fancy URL" setup
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   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 '/'.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   If it doesn't work, double-check that AllowOverride for the GNU Social
 | 
				
			||||||
 | 
					#       directory is 'All' in your Apache configuration file. This can be
 | 
				
			||||||
 | 
					#       * /etc/apache2/apache2.conf (generic)
 | 
				
			||||||
 | 
					#       * /etc/apache2/sites-available/default(on Debian and Ubuntu)
 | 
				
			||||||
 | 
					#       * ...many other variations depending on distribution...
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   See the Apache documentation for .htaccess files for more details:
 | 
				
			||||||
 | 
					#       https://httpd.apache.org/docs/2.4/howto/htaccess.html
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Also, check that mod_rewrite is installed and enabled:
 | 
				
			||||||
 | 
					#       https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<IfModule mod_rewrite.c>
 | 
					<IfModule mod_rewrite.c>
 | 
				
			||||||
  RewriteEngine On
 | 
					  RewriteEngine On
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # NOTE: change this to your actual StatusNet base URL path,
 | 
					  # NOTE: change this to your actual GNU social base URL path,
 | 
				
			||||||
  # minus the domain part:
 | 
					  # minus the domain part:
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  #   http://example.com/        => /
 | 
					  #   https://social.example.com/        => /
 | 
				
			||||||
  #   http://example.com/mublog/ => /mublog/
 | 
					  #   https://example.com/social/ => /social/
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  RewriteBase /
 | 
					  RewriteBase /
 | 
				
			||||||
  #RewriteBase /mublog/
 | 
					  #RewriteBase /mublog/
 | 
				
			||||||
@@ -26,7 +46,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<FilesMatch "\.(ini)">
 | 
					<FilesMatch "\.(ini)">
 | 
				
			||||||
  # For mod_access_compat in Apache <2.4
 | 
					  # For mod_access_compat in Apache <2.4
 | 
				
			||||||
  Order allow,deny
 | 
					  #Order allow,deny
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Use this instead for Apache >2.4 (mod_authz_host)
 | 
					  # Use this instead for Apache >2.4 (mod_authz_host)
 | 
				
			||||||
  # Require all denied
 | 
					  # Require all denied
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -265,7 +265,7 @@ function main()
 | 
				
			|||||||
    $site_ssl = common_config('site', 'ssl');
 | 
					    $site_ssl = common_config('site', 'ssl');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If the request is HTTP and it should be HTTPS...
 | 
					    // If the request is HTTP and it should be HTTPS...
 | 
				
			||||||
    if ($site_ssl != 'never' && !StatusNet::isHTTPS() && common_is_sensitive($args['action'])) {
 | 
					    if ($site_ssl != 'never' && !GNUsocial::isHTTPS() && common_is_sensitive($args['action'])) {
 | 
				
			||||||
        common_redirect(common_local_url($args['action'], $args));
 | 
					        common_redirect(common_local_url($args['action'], $args));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -265,10 +265,10 @@ class WebInstaller extends Installer
 | 
				
			|||||||
                    <li>
 | 
					                    <li>
 | 
				
			||||||
                        <label for="site_profile">Type of site</label>
 | 
					                        <label for="site_profile">Type of site</label>
 | 
				
			||||||
                        <select id="site_profile" name="site_profile">
 | 
					                        <select id="site_profile" name="site_profile">
 | 
				
			||||||
                            <option value="private">Private</option>
 | 
					 | 
				
			||||||
                            <option value="community">Community</option>
 | 
					                            <option value="community">Community</option>
 | 
				
			||||||
                            <option value ="public">Public</option>
 | 
					                            <option value="public">Public (open registration)</option>
 | 
				
			||||||
                            <option value="singleuser">Single User</option>
 | 
					                            <option value="singleuser">Single User</option>
 | 
				
			||||||
 | 
					                            <option value="private">Private (no federation)</option>
 | 
				
			||||||
                        </select>
 | 
					                        </select>
 | 
				
			||||||
                        <p class="form_guide">Initial access settings for your site</p>
 | 
					                        <p class="form_guide">Initial access settings for your site</p>
 | 
				
			||||||
                    </li>
 | 
					                    </li>
 | 
				
			||||||
 
 | 
				
			|||||||
| 
		 Before Width: | Height: | Size: 1.7 KiB  | 
| 
		 Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B  | 
| 
		 Before Width: | Height: | Size: 208 B After Width: | Height: | Size: 208 B  | 
| 
		 Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B  | 
| 
		 Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B  | 
| 
		 Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B  | 
| 
		 Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B  | 
| 
		 Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B  | 
| 
		 Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 280 B  | 
| 
		 Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB  | 
| 
		 Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB  | 
| 
		 Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB  | 
| 
		 Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB  | 
| 
		 Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB  | 
							
								
								
									
										202
									
								
								js/extlib/jquery-ui/css/smoothness/jquery-ui.css
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,8 +1,8 @@
 | 
				
			|||||||
/*! jQuery UI - v1.10.3 - 2013-09-12
 | 
					/*! jQuery UI - v1.11.3 - 2015-03-07
 | 
				
			||||||
* http://jqueryui.com
 | 
					* http://jqueryui.com
 | 
				
			||||||
* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css
 | 
					* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
 | 
				
			||||||
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
 | 
					* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
 | 
				
			||||||
* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
 | 
					* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Layout helpers
 | 
					/* Layout helpers
 | 
				
			||||||
----------------------------------*/
 | 
					----------------------------------*/
 | 
				
			||||||
@@ -48,7 +48,7 @@
 | 
				
			|||||||
	left: 0;
 | 
						left: 0;
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	opacity: 0;
 | 
						opacity: 0;
 | 
				
			||||||
	filter:Alpha(Opacity=0);
 | 
						filter:Alpha(Opacity=0); /* support: IE8 */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ui-front {
 | 
					.ui-front {
 | 
				
			||||||
@@ -86,6 +86,10 @@
 | 
				
			|||||||
	width: 100%;
 | 
						width: 100%;
 | 
				
			||||||
	height: 100%;
 | 
						height: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.ui-draggable-handle {
 | 
				
			||||||
 | 
						-ms-touch-action: none;
 | 
				
			||||||
 | 
						touch-action: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.ui-resizable {
 | 
					.ui-resizable {
 | 
				
			||||||
	position: relative;
 | 
						position: relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -93,6 +97,8 @@
 | 
				
			|||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	font-size: 0.1px;
 | 
						font-size: 0.1px;
 | 
				
			||||||
	display: block;
 | 
						display: block;
 | 
				
			||||||
 | 
						-ms-touch-action: none;
 | 
				
			||||||
 | 
						touch-action: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-resizable-disabled .ui-resizable-handle,
 | 
					.ui-resizable-disabled .ui-resizable-handle,
 | 
				
			||||||
.ui-resizable-autohide .ui-resizable-handle {
 | 
					.ui-resizable-autohide .ui-resizable-handle {
 | 
				
			||||||
@@ -154,25 +160,31 @@
 | 
				
			|||||||
	right: -5px;
 | 
						right: -5px;
 | 
				
			||||||
	top: -5px;
 | 
						top: -5px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectable {
 | 
				
			||||||
 | 
						-ms-touch-action: none;
 | 
				
			||||||
 | 
						touch-action: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.ui-selectable-helper {
 | 
					.ui-selectable-helper {
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	z-index: 100;
 | 
						z-index: 100;
 | 
				
			||||||
	border: 1px dotted black;
 | 
						border: 1px dotted black;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.ui-sortable-handle {
 | 
				
			||||||
 | 
						-ms-touch-action: none;
 | 
				
			||||||
 | 
						touch-action: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.ui-accordion .ui-accordion-header {
 | 
					.ui-accordion .ui-accordion-header {
 | 
				
			||||||
	display: block;
 | 
						display: block;
 | 
				
			||||||
	cursor: pointer;
 | 
						cursor: pointer;
 | 
				
			||||||
	position: relative;
 | 
						position: relative;
 | 
				
			||||||
	margin-top: 2px;
 | 
						margin: 2px 0 0 0;
 | 
				
			||||||
	padding: .5em .5em .5em .7em;
 | 
						padding: .5em .5em .5em .7em;
 | 
				
			||||||
	min-height: 0; /* support: IE7 */
 | 
						min-height: 0; /* support: IE7 */
 | 
				
			||||||
 | 
						font-size: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-accordion .ui-accordion-icons {
 | 
					.ui-accordion .ui-accordion-icons {
 | 
				
			||||||
	padding-left: 2.2em;
 | 
						padding-left: 2.2em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-accordion .ui-accordion-noicons {
 | 
					 | 
				
			||||||
	padding-left: .7em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.ui-accordion .ui-accordion-icons .ui-accordion-icons {
 | 
					.ui-accordion .ui-accordion-icons .ui-accordion-icons {
 | 
				
			||||||
	padding-left: 2.2em;
 | 
						padding-left: 2.2em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -347,12 +359,9 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	font-size: 1em;
 | 
						font-size: 1em;
 | 
				
			||||||
	margin: 1px 0;
 | 
						margin: 1px 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-datepicker select.ui-datepicker-month-year {
 | 
					 | 
				
			||||||
	width: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.ui-datepicker select.ui-datepicker-month,
 | 
					.ui-datepicker select.ui-datepicker-month,
 | 
				
			||||||
.ui-datepicker select.ui-datepicker-year {
 | 
					.ui-datepicker select.ui-datepicker-year {
 | 
				
			||||||
	width: 49%;
 | 
						width: 45%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-datepicker table {
 | 
					.ui-datepicker table {
 | 
				
			||||||
	width: 100%;
 | 
						width: 100%;
 | 
				
			||||||
@@ -466,6 +475,7 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	border-left-width: 1px;
 | 
						border-left-width: 1px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-dialog {
 | 
					.ui-dialog {
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	top: 0;
 | 
						top: 0;
 | 
				
			||||||
	left: 0;
 | 
						left: 0;
 | 
				
			||||||
@@ -488,7 +498,7 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	right: .3em;
 | 
						right: .3em;
 | 
				
			||||||
	top: 50%;
 | 
						top: 50%;
 | 
				
			||||||
	width: 21px;
 | 
						width: 20px;
 | 
				
			||||||
	margin: -10px 0 0 0;
 | 
						margin: -10px 0 0 0;
 | 
				
			||||||
	padding: 1px;
 | 
						padding: 1px;
 | 
				
			||||||
	height: 20px;
 | 
						height: 20px;
 | 
				
			||||||
@@ -526,72 +536,56 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu {
 | 
					.ui-menu {
 | 
				
			||||||
	list-style: none;
 | 
						list-style: none;
 | 
				
			||||||
	padding: 2px;
 | 
						padding: 0;
 | 
				
			||||||
	margin: 0;
 | 
						margin: 0;
 | 
				
			||||||
	display: block;
 | 
						display: block;
 | 
				
			||||||
	outline: none;
 | 
						outline: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu .ui-menu {
 | 
					.ui-menu .ui-menu {
 | 
				
			||||||
	margin-top: -3px;
 | 
					 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu .ui-menu-item {
 | 
					.ui-menu .ui-menu-item {
 | 
				
			||||||
 | 
						position: relative;
 | 
				
			||||||
	margin: 0;
 | 
						margin: 0;
 | 
				
			||||||
	padding: 0;
 | 
						padding: 3px 1em 3px .4em;
 | 
				
			||||||
	width: 100%;
 | 
						cursor: pointer;
 | 
				
			||||||
 | 
						min-height: 0; /* support: IE7 */
 | 
				
			||||||
	/* support: IE10, see #8844 */
 | 
						/* support: IE10, see #8844 */
 | 
				
			||||||
	list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
 | 
						list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu .ui-menu-divider {
 | 
					.ui-menu .ui-menu-divider {
 | 
				
			||||||
	margin: 5px -2px 5px -2px;
 | 
						margin: 5px 0;
 | 
				
			||||||
	height: 0;
 | 
						height: 0;
 | 
				
			||||||
	font-size: 0;
 | 
						font-size: 0;
 | 
				
			||||||
	line-height: 0;
 | 
						line-height: 0;
 | 
				
			||||||
	border-width: 1px 0 0 0;
 | 
						border-width: 1px 0 0 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu .ui-menu-item a {
 | 
					.ui-menu .ui-state-focus,
 | 
				
			||||||
	text-decoration: none;
 | 
					.ui-menu .ui-state-active {
 | 
				
			||||||
	display: block;
 | 
					 | 
				
			||||||
	padding: 2px .4em;
 | 
					 | 
				
			||||||
	line-height: 1.5;
 | 
					 | 
				
			||||||
	min-height: 0; /* support: IE7 */
 | 
					 | 
				
			||||||
	font-weight: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.ui-menu .ui-menu-item a.ui-state-focus,
 | 
					 | 
				
			||||||
.ui-menu .ui-menu-item a.ui-state-active {
 | 
					 | 
				
			||||||
	font-weight: normal;
 | 
					 | 
				
			||||||
	margin: -1px;
 | 
						margin: -1px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ui-menu .ui-state-disabled {
 | 
					 | 
				
			||||||
	font-weight: normal;
 | 
					 | 
				
			||||||
	margin: .4em 0 .2em;
 | 
					 | 
				
			||||||
	line-height: 1.5;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.ui-menu .ui-state-disabled a {
 | 
					 | 
				
			||||||
	cursor: default;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* icon support */
 | 
					/* icon support */
 | 
				
			||||||
.ui-menu-icons {
 | 
					.ui-menu-icons {
 | 
				
			||||||
	position: relative;
 | 
						position: relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-menu-icons .ui-menu-item a {
 | 
					.ui-menu-icons .ui-menu-item {
 | 
				
			||||||
	position: relative;
 | 
					 | 
				
			||||||
	padding-left: 2em;
 | 
						padding-left: 2em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* left-aligned */
 | 
					/* left-aligned */
 | 
				
			||||||
.ui-menu .ui-icon {
 | 
					.ui-menu .ui-icon {
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	top: .2em;
 | 
						top: 0;
 | 
				
			||||||
 | 
						bottom: 0;
 | 
				
			||||||
	left: .2em;
 | 
						left: .2em;
 | 
				
			||||||
 | 
						margin: auto 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* right-aligned */
 | 
					/* right-aligned */
 | 
				
			||||||
.ui-menu .ui-menu-icon {
 | 
					.ui-menu .ui-menu-icon {
 | 
				
			||||||
	position: static;
 | 
						left: auto;
 | 
				
			||||||
	float: right;
 | 
						right: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-progressbar {
 | 
					.ui-progressbar {
 | 
				
			||||||
	height: 2em;
 | 
						height: 2em;
 | 
				
			||||||
@@ -603,14 +597,63 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	height: 100%;
 | 
						height: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-progressbar .ui-progressbar-overlay {
 | 
					.ui-progressbar .ui-progressbar-overlay {
 | 
				
			||||||
	background: url("images/animated-overlay.gif");
 | 
						background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
 | 
				
			||||||
	height: 100%;
 | 
						height: 100%;
 | 
				
			||||||
	filter: alpha(opacity=25);
 | 
						filter: alpha(opacity=25); /* support: IE8 */
 | 
				
			||||||
	opacity: 0.25;
 | 
						opacity: 0.25;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-progressbar-indeterminate .ui-progressbar-value {
 | 
					.ui-progressbar-indeterminate .ui-progressbar-value {
 | 
				
			||||||
	background-image: none;
 | 
						background-image: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-menu {
 | 
				
			||||||
 | 
						padding: 0;
 | 
				
			||||||
 | 
						margin: 0;
 | 
				
			||||||
 | 
						position: absolute;
 | 
				
			||||||
 | 
						top: 0;
 | 
				
			||||||
 | 
						left: 0;
 | 
				
			||||||
 | 
						display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-menu .ui-menu {
 | 
				
			||||||
 | 
						overflow: auto;
 | 
				
			||||||
 | 
						/* Support: IE7 */
 | 
				
			||||||
 | 
						overflow-x: hidden;
 | 
				
			||||||
 | 
						padding-bottom: 1px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
 | 
				
			||||||
 | 
						font-size: 1em;
 | 
				
			||||||
 | 
						font-weight: bold;
 | 
				
			||||||
 | 
						line-height: 1.5;
 | 
				
			||||||
 | 
						padding: 2px 0.4em;
 | 
				
			||||||
 | 
						margin: 0.5em 0 0 0;
 | 
				
			||||||
 | 
						height: auto;
 | 
				
			||||||
 | 
						border: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-open {
 | 
				
			||||||
 | 
						display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-button {
 | 
				
			||||||
 | 
						display: inline-block;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						position: relative;
 | 
				
			||||||
 | 
						text-decoration: none;
 | 
				
			||||||
 | 
						cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-button span.ui-icon {
 | 
				
			||||||
 | 
						right: 0.5em;
 | 
				
			||||||
 | 
						left: auto;
 | 
				
			||||||
 | 
						margin-top: -8px;
 | 
				
			||||||
 | 
						position: absolute;
 | 
				
			||||||
 | 
						top: 50%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ui-selectmenu-button span.ui-selectmenu-text {
 | 
				
			||||||
 | 
						text-align: left;
 | 
				
			||||||
 | 
						padding: 0.4em 2.1em 0.4em 1em;
 | 
				
			||||||
 | 
						display: block;
 | 
				
			||||||
 | 
						line-height: 1.4;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						text-overflow: ellipsis;
 | 
				
			||||||
 | 
						white-space: nowrap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.ui-slider {
 | 
					.ui-slider {
 | 
				
			||||||
	position: relative;
 | 
						position: relative;
 | 
				
			||||||
	text-align: left;
 | 
						text-align: left;
 | 
				
			||||||
@@ -621,6 +664,8 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	width: 1.2em;
 | 
						width: 1.2em;
 | 
				
			||||||
	height: 1.2em;
 | 
						height: 1.2em;
 | 
				
			||||||
	cursor: default;
 | 
						cursor: default;
 | 
				
			||||||
 | 
						-ms-touch-action: none;
 | 
				
			||||||
 | 
						touch-action: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-slider .ui-slider-range {
 | 
					.ui-slider .ui-slider-range {
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
@@ -631,7 +676,7 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	background-position: 0 0;
 | 
						background-position: 0 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* For IE8 - See #6727 */
 | 
					/* support: IE8 - See #6727 */
 | 
				
			||||||
.ui-slider.ui-state-disabled .ui-slider-handle,
 | 
					.ui-slider.ui-state-disabled .ui-slider-handle,
 | 
				
			||||||
.ui-slider.ui-state-disabled .ui-slider-range {
 | 
					.ui-slider.ui-state-disabled .ui-slider-range {
 | 
				
			||||||
	filter: inherit;
 | 
						filter: inherit;
 | 
				
			||||||
@@ -704,13 +749,13 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	overflow: hidden;
 | 
						overflow: hidden;
 | 
				
			||||||
	right: 0;
 | 
						right: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* more specificity required here to overide default borders */
 | 
					/* more specificity required here to override default borders */
 | 
				
			||||||
.ui-spinner a.ui-spinner-button {
 | 
					.ui-spinner a.ui-spinner-button {
 | 
				
			||||||
	border-top: none;
 | 
						border-top: none;
 | 
				
			||||||
	border-bottom: none;
 | 
						border-bottom: none;
 | 
				
			||||||
	border-right: none;
 | 
						border-right: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* vertical centre icon */
 | 
					/* vertically center icon */
 | 
				
			||||||
.ui-spinner .ui-icon {
 | 
					.ui-spinner .ui-icon {
 | 
				
			||||||
	position: absolute;
 | 
						position: absolute;
 | 
				
			||||||
	margin-top: -8px;
 | 
						margin-top: -8px;
 | 
				
			||||||
@@ -747,7 +792,7 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	padding: 0;
 | 
						padding: 0;
 | 
				
			||||||
	white-space: nowrap;
 | 
						white-space: nowrap;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-tabs .ui-tabs-nav li a {
 | 
					.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
 | 
				
			||||||
	float: left;
 | 
						float: left;
 | 
				
			||||||
	padding: .5em 1em;
 | 
						padding: .5em 1em;
 | 
				
			||||||
	text-decoration: none;
 | 
						text-decoration: none;
 | 
				
			||||||
@@ -756,13 +801,12 @@ button.ui-button::-moz-focus-inner {
 | 
				
			|||||||
	margin-bottom: -1px;
 | 
						margin-bottom: -1px;
 | 
				
			||||||
	padding-bottom: 1px;
 | 
						padding-bottom: 1px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active a,
 | 
					.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
 | 
				
			||||||
.ui-tabs .ui-tabs-nav li.ui-state-disabled a,
 | 
					.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
 | 
				
			||||||
.ui-tabs .ui-tabs-nav li.ui-tabs-loading a {
 | 
					.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
 | 
				
			||||||
	cursor: text;
 | 
						cursor: text;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 | 
					.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
 | 
				
			||||||
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a {
 | 
					 | 
				
			||||||
	cursor: pointer;
 | 
						cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-tabs .ui-tabs-panel {
 | 
					.ui-tabs .ui-tabs-panel {
 | 
				
			||||||
@@ -801,7 +845,7 @@ body .ui-tooltip {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
.ui-widget-content {
 | 
					.ui-widget-content {
 | 
				
			||||||
	border: 1px solid #aaaaaa;
 | 
						border: 1px solid #aaaaaa;
 | 
				
			||||||
	background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;
 | 
						background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
 | 
				
			||||||
	color: #222222;
 | 
						color: #222222;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-widget-content a {
 | 
					.ui-widget-content a {
 | 
				
			||||||
@@ -809,7 +853,7 @@ body .ui-tooltip {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
.ui-widget-header {
 | 
					.ui-widget-header {
 | 
				
			||||||
	border: 1px solid #aaaaaa;
 | 
						border: 1px solid #aaaaaa;
 | 
				
			||||||
	background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;
 | 
						background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
 | 
				
			||||||
	color: #222222;
 | 
						color: #222222;
 | 
				
			||||||
	font-weight: bold;
 | 
						font-weight: bold;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -823,7 +867,7 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-state-default,
 | 
					.ui-widget-content .ui-state-default,
 | 
				
			||||||
.ui-widget-header .ui-state-default {
 | 
					.ui-widget-header .ui-state-default {
 | 
				
			||||||
	border: 1px solid #d3d3d3;
 | 
						border: 1px solid #d3d3d3;
 | 
				
			||||||
	background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
 | 
						background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
 | 
				
			||||||
	font-weight: normal;
 | 
						font-weight: normal;
 | 
				
			||||||
	color: #555555;
 | 
						color: #555555;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -840,14 +884,18 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-state-focus,
 | 
					.ui-widget-content .ui-state-focus,
 | 
				
			||||||
.ui-widget-header .ui-state-focus {
 | 
					.ui-widget-header .ui-state-focus {
 | 
				
			||||||
	border: 1px solid #999999;
 | 
						border: 1px solid #999999;
 | 
				
			||||||
	background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;
 | 
						background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
 | 
				
			||||||
	font-weight: normal;
 | 
						font-weight: normal;
 | 
				
			||||||
	color: #212121;
 | 
						color: #212121;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-hover a,
 | 
					.ui-state-hover a,
 | 
				
			||||||
.ui-state-hover a:hover,
 | 
					.ui-state-hover a:hover,
 | 
				
			||||||
.ui-state-hover a:link,
 | 
					.ui-state-hover a:link,
 | 
				
			||||||
.ui-state-hover a:visited {
 | 
					.ui-state-hover a:visited,
 | 
				
			||||||
 | 
					.ui-state-focus a,
 | 
				
			||||||
 | 
					.ui-state-focus a:hover,
 | 
				
			||||||
 | 
					.ui-state-focus a:link,
 | 
				
			||||||
 | 
					.ui-state-focus a:visited {
 | 
				
			||||||
	color: #212121;
 | 
						color: #212121;
 | 
				
			||||||
	text-decoration: none;
 | 
						text-decoration: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -855,7 +903,7 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-state-active,
 | 
					.ui-widget-content .ui-state-active,
 | 
				
			||||||
.ui-widget-header .ui-state-active {
 | 
					.ui-widget-header .ui-state-active {
 | 
				
			||||||
	border: 1px solid #aaaaaa;
 | 
						border: 1px solid #aaaaaa;
 | 
				
			||||||
	background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;
 | 
						background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
 | 
				
			||||||
	font-weight: normal;
 | 
						font-weight: normal;
 | 
				
			||||||
	color: #212121;
 | 
						color: #212121;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -872,7 +920,7 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-state-highlight,
 | 
					.ui-widget-content .ui-state-highlight,
 | 
				
			||||||
.ui-widget-header .ui-state-highlight {
 | 
					.ui-widget-header .ui-state-highlight {
 | 
				
			||||||
	border: 1px solid #fcefa1;
 | 
						border: 1px solid #fcefa1;
 | 
				
			||||||
	background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;
 | 
						background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
 | 
				
			||||||
	color: #363636;
 | 
						color: #363636;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-highlight a,
 | 
					.ui-state-highlight a,
 | 
				
			||||||
@@ -884,7 +932,7 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-state-error,
 | 
					.ui-widget-content .ui-state-error,
 | 
				
			||||||
.ui-widget-header .ui-state-error {
 | 
					.ui-widget-header .ui-state-error {
 | 
				
			||||||
	border: 1px solid #cd0a0a;
 | 
						border: 1px solid #cd0a0a;
 | 
				
			||||||
	background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
 | 
						background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
 | 
				
			||||||
	color: #cd0a0a;
 | 
						color: #cd0a0a;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-error a,
 | 
					.ui-state-error a,
 | 
				
			||||||
@@ -906,18 +954,18 @@ body .ui-tooltip {
 | 
				
			|||||||
.ui-widget-content .ui-priority-secondary,
 | 
					.ui-widget-content .ui-priority-secondary,
 | 
				
			||||||
.ui-widget-header .ui-priority-secondary {
 | 
					.ui-widget-header .ui-priority-secondary {
 | 
				
			||||||
	opacity: .7;
 | 
						opacity: .7;
 | 
				
			||||||
	filter:Alpha(Opacity=70);
 | 
						filter:Alpha(Opacity=70); /* support: IE8 */
 | 
				
			||||||
	font-weight: normal;
 | 
						font-weight: normal;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-disabled,
 | 
					.ui-state-disabled,
 | 
				
			||||||
.ui-widget-content .ui-state-disabled,
 | 
					.ui-widget-content .ui-state-disabled,
 | 
				
			||||||
.ui-widget-header .ui-state-disabled {
 | 
					.ui-widget-header .ui-state-disabled {
 | 
				
			||||||
	opacity: .35;
 | 
						opacity: .35;
 | 
				
			||||||
	filter:Alpha(Opacity=35);
 | 
						filter:Alpha(Opacity=35); /* support: IE8 */
 | 
				
			||||||
	background-image: none;
 | 
						background-image: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-disabled .ui-icon {
 | 
					.ui-state-disabled .ui-icon {
 | 
				
			||||||
	filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
 | 
						filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Icons
 | 
					/* Icons
 | 
				
			||||||
@@ -930,27 +978,27 @@ body .ui-tooltip {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
.ui-icon,
 | 
					.ui-icon,
 | 
				
			||||||
.ui-widget-content .ui-icon {
 | 
					.ui-widget-content .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_222222_256x240.png);
 | 
						background-image: url("images/ui-icons_222222_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-widget-header .ui-icon {
 | 
					.ui-widget-header .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_222222_256x240.png);
 | 
						background-image: url("images/ui-icons_222222_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-default .ui-icon {
 | 
					.ui-state-default .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_888888_256x240.png);
 | 
						background-image: url("images/ui-icons_888888_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-hover .ui-icon,
 | 
					.ui-state-hover .ui-icon,
 | 
				
			||||||
.ui-state-focus .ui-icon {
 | 
					.ui-state-focus .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_454545_256x240.png);
 | 
						background-image: url("images/ui-icons_454545_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-active .ui-icon {
 | 
					.ui-state-active .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_454545_256x240.png);
 | 
						background-image: url("images/ui-icons_454545_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-highlight .ui-icon {
 | 
					.ui-state-highlight .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_2e83ff_256x240.png);
 | 
						background-image: url("images/ui-icons_2e83ff_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-state-error .ui-icon,
 | 
					.ui-state-error .ui-icon,
 | 
				
			||||||
.ui-state-error-text .ui-icon {
 | 
					.ui-state-error-text .ui-icon {
 | 
				
			||||||
	background-image: url(images/ui-icons_cd0a0a_256x240.png);
 | 
						background-image: url("images/ui-icons_cd0a0a_256x240.png");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* positioning */
 | 
					/* positioning */
 | 
				
			||||||
@@ -1163,15 +1211,15 @@ body .ui-tooltip {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Overlays */
 | 
					/* Overlays */
 | 
				
			||||||
.ui-widget-overlay {
 | 
					.ui-widget-overlay {
 | 
				
			||||||
	background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
 | 
						background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
 | 
				
			||||||
	opacity: .3;
 | 
						opacity: .3;
 | 
				
			||||||
	filter: Alpha(Opacity=30);
 | 
						filter: Alpha(Opacity=30); /* support: IE8 */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.ui-widget-shadow {
 | 
					.ui-widget-shadow {
 | 
				
			||||||
	margin: -8px 0 0 -8px;
 | 
						margin: -8px 0 0 -8px;
 | 
				
			||||||
	padding: 8px;
 | 
						padding: 8px;
 | 
				
			||||||
	background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
 | 
						background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
 | 
				
			||||||
	opacity: .3;
 | 
						opacity: .3;
 | 
				
			||||||
	filter: Alpha(Opacity=30);
 | 
						filter: Alpha(Opacity=30); /* support: IE8 */
 | 
				
			||||||
	border-radius: 8px;
 | 
						border-radius: 8px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5585
									
								
								js/extlib/jquery-ui/jquery-ui.js
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,5 +1,5 @@
 | 
				
			|||||||
/*!
 | 
					/*!
 | 
				
			||||||
 * jQuery Cookie Plugin v1.3.1
 | 
					 * jQuery Cookie Plugin v1.4.1
 | 
				
			||||||
 * https://github.com/carhartl/jquery-cookie
 | 
					 * https://github.com/carhartl/jquery-cookie
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright 2013 Klaus Hartl
 | 
					 * Copyright 2013 Klaus Hartl
 | 
				
			||||||
@@ -7,57 +7,65 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
(function (factory) {
 | 
					(function (factory) {
 | 
				
			||||||
	if (typeof define === 'function' && define.amd) {
 | 
						if (typeof define === 'function' && define.amd) {
 | 
				
			||||||
		// AMD. Register as anonymous module.
 | 
							// AMD
 | 
				
			||||||
		define(['jquery'], factory);
 | 
							define(['jquery'], factory);
 | 
				
			||||||
 | 
						} else if (typeof exports === 'object') {
 | 
				
			||||||
 | 
							// CommonJS
 | 
				
			||||||
 | 
							factory(require('jquery'));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Browser globals.
 | 
							// Browser globals
 | 
				
			||||||
		factory(jQuery);
 | 
							factory(jQuery);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}(function ($) {
 | 
					}(function ($) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var pluses = /\+/g;
 | 
						var pluses = /\+/g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function decode(s) {
 | 
						function encode(s) {
 | 
				
			||||||
		if (config.raw) {
 | 
							return config.raw ? s : encodeURIComponent(s);
 | 
				
			||||||
			return s;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			// If we can't decode the cookie, ignore it, it's unusable.
 | 
					 | 
				
			||||||
			return decodeURIComponent(s.replace(pluses, ' '));
 | 
					 | 
				
			||||||
		} catch(e) {}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function decodeAndParse(s) {
 | 
						function decode(s) {
 | 
				
			||||||
 | 
							return config.raw ? s : decodeURIComponent(s);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function stringifyCookieValue(value) {
 | 
				
			||||||
 | 
							return encode(config.json ? JSON.stringify(value) : String(value));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function parseCookieValue(s) {
 | 
				
			||||||
		if (s.indexOf('"') === 0) {
 | 
							if (s.indexOf('"') === 0) {
 | 
				
			||||||
			// This is a quoted cookie as according to RFC2068, unescape...
 | 
								// This is a quoted cookie as according to RFC2068, unescape...
 | 
				
			||||||
			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
 | 
								s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		s = decode(s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
 | 
								// Replace server-side written pluses with spaces.
 | 
				
			||||||
 | 
								// If we can't decode the cookie, ignore it, it's unusable.
 | 
				
			||||||
			// If we can't parse the cookie, ignore it, it's unusable.
 | 
								// If we can't parse the cookie, ignore it, it's unusable.
 | 
				
			||||||
 | 
								s = decodeURIComponent(s.replace(pluses, ' '));
 | 
				
			||||||
			return config.json ? JSON.parse(s) : s;
 | 
								return config.json ? JSON.parse(s) : s;
 | 
				
			||||||
		} catch(e) {}
 | 
							} catch(e) {}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function read(s, converter) {
 | 
				
			||||||
 | 
							var value = config.raw ? s : parseCookieValue(s);
 | 
				
			||||||
 | 
							return $.isFunction(converter) ? converter(value) : value;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var config = $.cookie = function (key, value, options) {
 | 
						var config = $.cookie = function (key, value, options) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Write
 | 
							// Write
 | 
				
			||||||
		if (value !== undefined) {
 | 
					
 | 
				
			||||||
 | 
							if (value !== undefined && !$.isFunction(value)) {
 | 
				
			||||||
			options = $.extend({}, config.defaults, options);
 | 
								options = $.extend({}, config.defaults, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (typeof options.expires === 'number') {
 | 
								if (typeof options.expires === 'number') {
 | 
				
			||||||
				var days = options.expires, t = options.expires = new Date();
 | 
									var days = options.expires, t = options.expires = new Date();
 | 
				
			||||||
				t.setDate(t.getDate() + days);
 | 
									t.setTime(+t + days * 864e+5);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			value = config.json ? JSON.stringify(value) : String(value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return (document.cookie = [
 | 
								return (document.cookie = [
 | 
				
			||||||
				config.raw ? key : encodeURIComponent(key),
 | 
									encode(key), '=', stringifyCookieValue(value),
 | 
				
			||||||
				'=',
 | 
					 | 
				
			||||||
				config.raw ? value : encodeURIComponent(value),
 | 
					 | 
				
			||||||
				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
 | 
									options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
 | 
				
			||||||
				options.path    ? '; path=' + options.path : '',
 | 
									options.path    ? '; path=' + options.path : '',
 | 
				
			||||||
				options.domain  ? '; domain=' + options.domain : '',
 | 
									options.domain  ? '; domain=' + options.domain : '',
 | 
				
			||||||
@@ -80,12 +88,13 @@
 | 
				
			|||||||
			var cookie = parts.join('=');
 | 
								var cookie = parts.join('=');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (key && key === name) {
 | 
								if (key && key === name) {
 | 
				
			||||||
				result = decodeAndParse(cookie);
 | 
									// If second argument (value) is a function it's a converter...
 | 
				
			||||||
 | 
									result = read(cookie, value);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Prevent storing a cookie that we couldn't decode.
 | 
								// Prevent storing a cookie that we couldn't decode.
 | 
				
			||||||
			if (!key && (cookie = decodeAndParse(cookie)) !== undefined) {
 | 
								if (!key && (cookie = read(cookie)) !== undefined) {
 | 
				
			||||||
				result[name] = cookie;
 | 
									result[name] = cookie;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -96,12 +105,13 @@
 | 
				
			|||||||
	config.defaults = {};
 | 
						config.defaults = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$.removeCookie = function (key, options) {
 | 
						$.removeCookie = function (key, options) {
 | 
				
			||||||
		if ($.cookie(key) !== undefined) {
 | 
							if ($.cookie(key) === undefined) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Must not alter options, thus extending a fresh object...
 | 
							// Must not alter options, thus extending a fresh object...
 | 
				
			||||||
		$.cookie(key, '', $.extend({}, options, { expires: -1 }));
 | 
							$.cookie(key, '', $.extend({}, options, { expires: -1 }));
 | 
				
			||||||
			return true;
 | 
							return !$.cookie(key);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,28 @@
 | 
				
			|||||||
/*!
 | 
					/*!
 | 
				
			||||||
 * jQuery Form Plugin
 | 
					 * jQuery Form Plugin
 | 
				
			||||||
 * version: 3.43.0-2013.09.03
 | 
					 * version: 3.51.0-2014.06.20
 | 
				
			||||||
 * Requires jQuery v1.5 or later
 | 
					 * Requires jQuery v1.5 or later
 | 
				
			||||||
 * Copyright (c) 2013 M. Alsup
 | 
					 * Copyright (c) 2014 M. Alsup
 | 
				
			||||||
 * Examples and documentation at: http://malsup.com/jquery/form/
 | 
					 * Examples and documentation at: http://malsup.com/jquery/form/
 | 
				
			||||||
 * Project repository: https://github.com/malsup/form
 | 
					 * Project repository: https://github.com/malsup/form
 | 
				
			||||||
 * Dual licensed under the MIT and GPL licenses.
 | 
					 * Dual licensed under the MIT and GPL licenses.
 | 
				
			||||||
 * https://github.com/malsup/form#copyright-and-license
 | 
					 * https://github.com/malsup/form#copyright-and-license
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
/*global ActiveXObject */
 | 
					/*global ActiveXObject */
 | 
				
			||||||
;(function($) {
 | 
					
 | 
				
			||||||
 | 
					// AMD support
 | 
				
			||||||
 | 
					(function (factory) {
 | 
				
			||||||
 | 
					    "use strict";
 | 
				
			||||||
 | 
					    if (typeof define === 'function' && define.amd) {
 | 
				
			||||||
 | 
					        // using AMD; register as anon module
 | 
				
			||||||
 | 
					        define(['jquery'], factory);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // no AMD; invoke directly
 | 
				
			||||||
 | 
					        factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(function($) {
 | 
				
			||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -63,11 +76,13 @@ var hasProp = !!$.fn.prop;
 | 
				
			|||||||
// contains inputs with names like "action" or "method"; in those
 | 
					// contains inputs with names like "action" or "method"; in those
 | 
				
			||||||
// cases "prop" returns the element
 | 
					// cases "prop" returns the element
 | 
				
			||||||
$.fn.attr2 = function() {
 | 
					$.fn.attr2 = function() {
 | 
				
			||||||
    if ( ! hasProp )
 | 
					    if ( ! hasProp ) {
 | 
				
			||||||
        return this.attr.apply(this, arguments);
 | 
					        return this.attr.apply(this, arguments);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    var val = this.prop.apply(this, arguments);
 | 
					    var val = this.prop.apply(this, arguments);
 | 
				
			||||||
    if ( ( val && val.jquery ) || typeof val === 'string' )
 | 
					    if ( ( val && val.jquery ) || typeof val === 'string' ) {
 | 
				
			||||||
        return val;
 | 
					        return val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return this.attr.apply(this, arguments);
 | 
					    return this.attr.apply(this, arguments);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,7 +224,7 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // [value] (issue #113), also see comment:
 | 
					    // [value] (issue #113), also see comment:
 | 
				
			||||||
    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
 | 
					    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
 | 
				
			||||||
    var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() != ''; });
 | 
					    var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var hasFileInputs = fileInputs.length > 0;
 | 
					    var hasFileInputs = fileInputs.length > 0;
 | 
				
			||||||
    var mp = 'multipart/form-data';
 | 
					    var mp = 'multipart/form-data';
 | 
				
			||||||
@@ -245,8 +260,9 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
    $form.removeData('jqxhr').data('jqxhr', jqxhr);
 | 
					    $form.removeData('jqxhr').data('jqxhr', jqxhr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // clear element array
 | 
					    // clear element array
 | 
				
			||||||
    for (var k=0; k < elements.length; k++)
 | 
					    for (var k=0; k < elements.length; k++) {
 | 
				
			||||||
        elements[k] = null;
 | 
					        elements[k] = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // fire 'notify' event
 | 
					    // fire 'notify' event
 | 
				
			||||||
    this.trigger('form-submit-notify', [this, options]);
 | 
					    this.trigger('form-submit-notify', [this, options]);
 | 
				
			||||||
@@ -278,10 +294,12 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (options.extraData) {
 | 
					        if (options.extraData) {
 | 
				
			||||||
            var serializedData = deepSerialize(options.extraData);
 | 
					            var serializedData = deepSerialize(options.extraData);
 | 
				
			||||||
            for (i=0; i < serializedData.length; i++)
 | 
					            for (i=0; i < serializedData.length; i++) {
 | 
				
			||||||
                if (serializedData[i])
 | 
					                if (serializedData[i]) {
 | 
				
			||||||
                    formdata.append(serializedData[i][0], serializedData[i][1]);
 | 
					                    formdata.append(serializedData[i][0], serializedData[i][1]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options.data = null;
 | 
					        options.data = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -314,9 +332,16 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
        s.data = null;
 | 
					        s.data = null;
 | 
				
			||||||
        var beforeSend = s.beforeSend;
 | 
					        var beforeSend = s.beforeSend;
 | 
				
			||||||
        s.beforeSend = function(xhr, o) {
 | 
					        s.beforeSend = function(xhr, o) {
 | 
				
			||||||
 | 
					            //Send FormData() provided by user
 | 
				
			||||||
 | 
					            if (options.formData) {
 | 
				
			||||||
 | 
					                o.data = options.formData;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                o.data = formdata;
 | 
					                o.data = formdata;
 | 
				
			||||||
                if(beforeSend)
 | 
					            }
 | 
				
			||||||
 | 
					            if(beforeSend) {
 | 
				
			||||||
                beforeSend.call(this, xhr, o);
 | 
					                beforeSend.call(this, xhr, o);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return $.ajax(s);
 | 
					        return $.ajax(s);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -335,12 +360,14 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
            // ensure that every serialized input is still enabled
 | 
					            // ensure that every serialized input is still enabled
 | 
				
			||||||
            for (i=0; i < elements.length; i++) {
 | 
					            for (i=0; i < elements.length; i++) {
 | 
				
			||||||
                el = $(elements[i]);
 | 
					                el = $(elements[i]);
 | 
				
			||||||
                if ( hasProp )
 | 
					                if ( hasProp ) {
 | 
				
			||||||
                    el.prop('disabled', false);
 | 
					                    el.prop('disabled', false);
 | 
				
			||||||
                else
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
                    el.removeAttr('disabled');
 | 
					                    el.removeAttr('disabled');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s = $.extend(true, {}, $.ajaxSettings, options);
 | 
					        s = $.extend(true, {}, $.ajaxSettings, options);
 | 
				
			||||||
        s.context = s.context || s;
 | 
					        s.context = s.context || s;
 | 
				
			||||||
@@ -348,11 +375,13 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
        if (s.iframeTarget) {
 | 
					        if (s.iframeTarget) {
 | 
				
			||||||
            $io = $(s.iframeTarget);
 | 
					            $io = $(s.iframeTarget);
 | 
				
			||||||
            n = $io.attr2('name');
 | 
					            n = $io.attr2('name');
 | 
				
			||||||
            if (!n)
 | 
					            if (!n) {
 | 
				
			||||||
                $io.attr2('name', id);
 | 
					                $io.attr2('name', id);
 | 
				
			||||||
            else
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                id = n;
 | 
					                id = n;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
 | 
					            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
 | 
				
			||||||
            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
 | 
					            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
 | 
				
			||||||
@@ -383,13 +412,16 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                $io.attr('src', s.iframeSrc); // abort op in progress
 | 
					                $io.attr('src', s.iframeSrc); // abort op in progress
 | 
				
			||||||
                xhr.error = e;
 | 
					                xhr.error = e;
 | 
				
			||||||
                if (s.error)
 | 
					                if (s.error) {
 | 
				
			||||||
                    s.error.call(s.context, xhr, e, status);
 | 
					                    s.error.call(s.context, xhr, e, status);
 | 
				
			||||||
                if (g)
 | 
					                }
 | 
				
			||||||
 | 
					                if (g) {
 | 
				
			||||||
                    $.event.trigger("ajaxError", [xhr, s, e]);
 | 
					                    $.event.trigger("ajaxError", [xhr, s, e]);
 | 
				
			||||||
                if (s.complete)
 | 
					                }
 | 
				
			||||||
 | 
					                if (s.complete) {
 | 
				
			||||||
                    s.complete.call(s.context, xhr, e);
 | 
					                    s.complete.call(s.context, xhr, e);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g = s.global;
 | 
					        g = s.global;
 | 
				
			||||||
@@ -475,7 +507,10 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
        // take a breath so that pending repaints get some cpu time before the upload starts
 | 
					        // take a breath so that pending repaints get some cpu time before the upload starts
 | 
				
			||||||
        function doSubmit() {
 | 
					        function doSubmit() {
 | 
				
			||||||
            // make sure form attrs are set
 | 
					            // make sure form attrs are set
 | 
				
			||||||
            var t = $form.attr2('target'), a = $form.attr2('action');
 | 
					            var t = $form.attr2('target'), 
 | 
				
			||||||
 | 
					                a = $form.attr2('action'), 
 | 
				
			||||||
 | 
					                mp = 'multipart/form-data',
 | 
				
			||||||
 | 
					                et = $form.attr('enctype') || $form.attr('encoding') || mp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // update form attrs in IE friendly way
 | 
					            // update form attrs in IE friendly way
 | 
				
			||||||
            form.setAttribute('target',id);
 | 
					            form.setAttribute('target',id);
 | 
				
			||||||
@@ -504,14 +539,16 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    var state = getDoc(io).readyState;
 | 
					                    var state = getDoc(io).readyState;
 | 
				
			||||||
                    log('state = ' + state);
 | 
					                    log('state = ' + state);
 | 
				
			||||||
                    if (state && state.toLowerCase() == 'uninitialized')
 | 
					                    if (state && state.toLowerCase() == 'uninitialized') {
 | 
				
			||||||
                        setTimeout(checkState,50);
 | 
					                        setTimeout(checkState,50);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                catch(e) {
 | 
					                catch(e) {
 | 
				
			||||||
                    log('Server abort: ' , e, ' (', e.name, ')');
 | 
					                    log('Server abort: ' , e, ' (', e.name, ')');
 | 
				
			||||||
                    cb(SERVER_ABORT);
 | 
					                    cb(SERVER_ABORT);
 | 
				
			||||||
                    if (timeoutHandle)
 | 
					                    if (timeoutHandle) {
 | 
				
			||||||
                        clearTimeout(timeoutHandle);
 | 
					                        clearTimeout(timeoutHandle);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    timeoutHandle = undefined;
 | 
					                    timeoutHandle = undefined;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -540,10 +577,12 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
                    // add iframe to doc and submit the form
 | 
					                    // add iframe to doc and submit the form
 | 
				
			||||||
                    $io.appendTo('body');
 | 
					                    $io.appendTo('body');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (io.attachEvent)
 | 
					                if (io.attachEvent) {
 | 
				
			||||||
                    io.attachEvent('onload', cb);
 | 
					                    io.attachEvent('onload', cb);
 | 
				
			||||||
                else
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
                    io.addEventListener('load', cb, false);
 | 
					                    io.addEventListener('load', cb, false);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                setTimeout(checkState,15);
 | 
					                setTimeout(checkState,15);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
@@ -557,6 +596,7 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
            finally {
 | 
					            finally {
 | 
				
			||||||
                // reset attrs and remove "extra" input elements
 | 
					                // reset attrs and remove "extra" input elements
 | 
				
			||||||
                form.setAttribute('action',a);
 | 
					                form.setAttribute('action',a);
 | 
				
			||||||
 | 
					                form.setAttribute('enctype', et); // #380
 | 
				
			||||||
                if(t) {
 | 
					                if(t) {
 | 
				
			||||||
                    form.setAttribute('target', t);
 | 
					                    form.setAttribute('target', t);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
@@ -598,13 +638,16 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (!doc || doc.location.href == s.iframeSrc) {
 | 
					            if (!doc || doc.location.href == s.iframeSrc) {
 | 
				
			||||||
                // response not received yet
 | 
					                // response not received yet
 | 
				
			||||||
                if (!timedOut)
 | 
					                if (!timedOut) {
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            if (io.detachEvent)
 | 
					            }
 | 
				
			||||||
 | 
					            if (io.detachEvent) {
 | 
				
			||||||
                io.detachEvent('onload', cb);
 | 
					                io.detachEvent('onload', cb);
 | 
				
			||||||
            else
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
                io.removeEventListener('load', cb, false);
 | 
					                io.removeEventListener('load', cb, false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var status = 'success', errMsg;
 | 
					            var status = 'success', errMsg;
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
@@ -631,8 +674,9 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
                var docRoot = doc.body ? doc.body : doc.documentElement;
 | 
					                var docRoot = doc.body ? doc.body : doc.documentElement;
 | 
				
			||||||
                xhr.responseText = docRoot ? docRoot.innerHTML : null;
 | 
					                xhr.responseText = docRoot ? docRoot.innerHTML : null;
 | 
				
			||||||
                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
 | 
					                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
 | 
				
			||||||
                if (isXml)
 | 
					                if (isXml) {
 | 
				
			||||||
                    s.dataType = 'xml';
 | 
					                    s.dataType = 'xml';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                xhr.getResponseHeader = function(header){
 | 
					                xhr.getResponseHeader = function(header){
 | 
				
			||||||
                    var headers = {'content-type': s.dataType};
 | 
					                    var headers = {'content-type': s.dataType};
 | 
				
			||||||
                    return headers[header.toLowerCase()];
 | 
					                    return headers[header.toLowerCase()];
 | 
				
			||||||
@@ -695,42 +739,52 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
 | 
					            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
 | 
				
			||||||
            if (status === 'success') {
 | 
					            if (status === 'success') {
 | 
				
			||||||
                if (s.success)
 | 
					                if (s.success) {
 | 
				
			||||||
                    s.success.call(s.context, data, 'success', xhr);
 | 
					                    s.success.call(s.context, data, 'success', xhr);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                deferred.resolve(xhr.responseText, 'success', xhr);
 | 
					                deferred.resolve(xhr.responseText, 'success', xhr);
 | 
				
			||||||
                if (g)
 | 
					                if (g) {
 | 
				
			||||||
                    $.event.trigger("ajaxSuccess", [xhr, s]);
 | 
					                    $.event.trigger("ajaxSuccess", [xhr, s]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            else if (status) {
 | 
					            else if (status) {
 | 
				
			||||||
                if (errMsg === undefined)
 | 
					                if (errMsg === undefined) {
 | 
				
			||||||
                    errMsg = xhr.statusText;
 | 
					                    errMsg = xhr.statusText;
 | 
				
			||||||
                if (s.error)
 | 
					                }
 | 
				
			||||||
 | 
					                if (s.error) {
 | 
				
			||||||
                    s.error.call(s.context, xhr, status, errMsg);
 | 
					                    s.error.call(s.context, xhr, status, errMsg);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                deferred.reject(xhr, 'error', errMsg);
 | 
					                deferred.reject(xhr, 'error', errMsg);
 | 
				
			||||||
                if (g)
 | 
					                if (g) {
 | 
				
			||||||
                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
 | 
					                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (g)
 | 
					            if (g) {
 | 
				
			||||||
                $.event.trigger("ajaxComplete", [xhr, s]);
 | 
					                $.event.trigger("ajaxComplete", [xhr, s]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (g && ! --$.active) {
 | 
					            if (g && ! --$.active) {
 | 
				
			||||||
                $.event.trigger("ajaxStop");
 | 
					                $.event.trigger("ajaxStop");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (s.complete)
 | 
					            if (s.complete) {
 | 
				
			||||||
                s.complete.call(s.context, xhr, status);
 | 
					                s.complete.call(s.context, xhr, status);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            callbackProcessed = true;
 | 
					            callbackProcessed = true;
 | 
				
			||||||
            if (s.timeout)
 | 
					            if (s.timeout) {
 | 
				
			||||||
                clearTimeout(timeoutHandle);
 | 
					                clearTimeout(timeoutHandle);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // clean up
 | 
					            // clean up
 | 
				
			||||||
            setTimeout(function() {
 | 
					            setTimeout(function() {
 | 
				
			||||||
                if (!s.iframeTarget)
 | 
					                if (!s.iframeTarget) {
 | 
				
			||||||
                    $io.remove();
 | 
					                    $io.remove();
 | 
				
			||||||
                else  //adding else to clean up existing iframe response.
 | 
					                }
 | 
				
			||||||
 | 
					                else { //adding else to clean up existing iframe response.
 | 
				
			||||||
                    $io.attr('src', s.iframeSrc);
 | 
					                    $io.attr('src', s.iframeSrc);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                xhr.responseXML = null;
 | 
					                xhr.responseXML = null;
 | 
				
			||||||
            }, 100);
 | 
					            }, 100);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -758,9 +812,10 @@ $.fn.ajaxSubmit = function(options) {
 | 
				
			|||||||
                data = xml ? xhr.responseXML : xhr.responseText;
 | 
					                data = xml ? xhr.responseXML : xhr.responseText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (xml && data.documentElement.nodeName === 'parsererror') {
 | 
					            if (xml && data.documentElement.nodeName === 'parsererror') {
 | 
				
			||||||
                if ($.error)
 | 
					                if ($.error) {
 | 
				
			||||||
                    $.error('parsererror');
 | 
					                    $.error('parsererror');
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (s && s.dataFilter) {
 | 
					            if (s && s.dataFilter) {
 | 
				
			||||||
                data = s.dataFilter(data, type);
 | 
					                data = s.dataFilter(data, type);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -832,7 +887,7 @@ function doAjaxSubmit(e) {
 | 
				
			|||||||
    var options = e.data;
 | 
					    var options = e.data;
 | 
				
			||||||
    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
 | 
					    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
 | 
				
			||||||
        e.preventDefault();
 | 
					        e.preventDefault();
 | 
				
			||||||
        $(this).ajaxSubmit(options);
 | 
					        $(e.target).ajaxSubmit(options); // #365
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -891,8 +946,23 @@ $.fn.formToArray = function(semantic, elements) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var form = this[0];
 | 
					    var form = this[0];
 | 
				
			||||||
 | 
					    var formId = this.attr('id');
 | 
				
			||||||
    var els = semantic ? form.getElementsByTagName('*') : form.elements;
 | 
					    var els = semantic ? form.getElementsByTagName('*') : form.elements;
 | 
				
			||||||
    if (!els) {
 | 
					    var els2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390
 | 
				
			||||||
 | 
					        els = $(els).get();  // convert to standard array
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // #386; account for inputs outside the form which use the 'form' attribute
 | 
				
			||||||
 | 
					    if ( formId ) {
 | 
				
			||||||
 | 
					        els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
 | 
				
			||||||
 | 
					        if ( els2.length ) {
 | 
				
			||||||
 | 
					            els = (els || []).concat(els2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!els || !els.length) {
 | 
				
			||||||
        return a;
 | 
					        return a;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -915,15 +985,17 @@ $.fn.formToArray = function(semantic, elements) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        v = $.fieldValue(el, true);
 | 
					        v = $.fieldValue(el, true);
 | 
				
			||||||
        if (v && v.constructor == Array) {
 | 
					        if (v && v.constructor == Array) {
 | 
				
			||||||
            if (elements)
 | 
					            if (elements) {
 | 
				
			||||||
                elements.push(el);
 | 
					                elements.push(el);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            for(j=0, jmax=v.length; j < jmax; j++) {
 | 
					            for(j=0, jmax=v.length; j < jmax; j++) {
 | 
				
			||||||
                a.push({name: n, value: v[j]});
 | 
					                a.push({name: n, value: v[j]});
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (feature.fileapi && el.type == 'file') {
 | 
					        else if (feature.fileapi && el.type == 'file') {
 | 
				
			||||||
            if (elements)
 | 
					            if (elements) {
 | 
				
			||||||
                elements.push(el);
 | 
					                elements.push(el);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            var files = el.files;
 | 
					            var files = el.files;
 | 
				
			||||||
            if (files.length) {
 | 
					            if (files.length) {
 | 
				
			||||||
                for (j=0; j < files.length; j++) {
 | 
					                for (j=0; j < files.length; j++) {
 | 
				
			||||||
@@ -936,8 +1008,9 @@ $.fn.formToArray = function(semantic, elements) {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (v !== null && typeof v != 'undefined') {
 | 
					        else if (v !== null && typeof v != 'undefined') {
 | 
				
			||||||
            if (elements)
 | 
					            if (elements) {
 | 
				
			||||||
                elements.push(el);
 | 
					                elements.push(el);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            a.push({name: n, value: v, type: el.type, required: el.required});
 | 
					            a.push({name: n, value: v, type: el.type, required: el.required});
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -1033,11 +1106,13 @@ $.fn.fieldValue = function(successful) {
 | 
				
			|||||||
        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
 | 
					        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (v.constructor == Array)
 | 
					        if (v.constructor == Array) {
 | 
				
			||||||
            $.merge(val, v);
 | 
					            $.merge(val, v);
 | 
				
			||||||
        else
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
            val.push(v);
 | 
					            val.push(v);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return val;
 | 
					    return val;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1070,7 +1145,7 @@ $.fieldValue = function(el, successful) {
 | 
				
			|||||||
            if (op.selected) {
 | 
					            if (op.selected) {
 | 
				
			||||||
                var v = op.value;
 | 
					                var v = op.value;
 | 
				
			||||||
                if (!v) { // extra pain for IE...
 | 
					                if (!v) { // extra pain for IE...
 | 
				
			||||||
                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
 | 
					                    v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (one) {
 | 
					                if (one) {
 | 
				
			||||||
                    return v;
 | 
					                    return v;
 | 
				
			||||||
@@ -1126,9 +1201,10 @@ $.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
 | 
				
			|||||||
            //  $('#myForm').clearForm('.special:hidden')
 | 
					            //  $('#myForm').clearForm('.special:hidden')
 | 
				
			||||||
            // the above would clean hidden inputs that have the class of 'special'
 | 
					            // the above would clean hidden inputs that have the class of 'special'
 | 
				
			||||||
            if ( (includeHidden === true && /hidden/.test(t)) ||
 | 
					            if ( (includeHidden === true && /hidden/.test(t)) ||
 | 
				
			||||||
                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
 | 
					                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) {
 | 
				
			||||||
                this.value = '';
 | 
					                this.value = '';
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1186,8 +1262,9 @@ $.fn.ajaxSubmit.debug = false;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// helper fn for console logging
 | 
					// helper fn for console logging
 | 
				
			||||||
function log() {
 | 
					function log() {
 | 
				
			||||||
    if (!$.fn.ajaxSubmit.debug)
 | 
					    if (!$.fn.ajaxSubmit.debug) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
 | 
					    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
 | 
				
			||||||
    if (window.console && window.console.log) {
 | 
					    if (window.console && window.console.log) {
 | 
				
			||||||
        window.console.log(msg);
 | 
					        window.console.log(msg);
 | 
				
			||||||
@@ -1197,4 +1274,4 @@ function log() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
})( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
 | 
					}));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,168 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * @license In-Field Label jQuery Plugin
 | 
					 | 
				
			||||||
 * http://fuelyourcoding.com/scripts/infield.html
 | 
					 | 
				
			||||||
 * http://github.com/streetpc/jquery-infieldlabels
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (c) 2009 Doug Neiner, Adrien Lavoillotte
 | 
					 | 
				
			||||||
 * Dual licensed under the MIT and GPL licenses, see:
 | 
					 | 
				
			||||||
 * http://docs.jquery.com/License
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @version 0.2.1
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
(function ($) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // private constants
 | 
					 | 
				
			||||||
  //  - states
 | 
					 | 
				
			||||||
  var BLUR = 0, // field is empty & unfocused
 | 
					 | 
				
			||||||
      FOCUS = 1, // field is empty & focused
 | 
					 | 
				
			||||||
      NOT_EMPTY = 2, // field is not empty
 | 
					 | 
				
			||||||
  //  - accepted input type 
 | 
					 | 
				
			||||||
      INPUT_TYPE = /^(?:text|password|search|number|tel|url|email|date(?:time(?:-local)?)?|time|month|week)?$/,
 | 
					 | 
				
			||||||
  //  - state transitions
 | 
					 | 
				
			||||||
      T = function(from, to) { return (from << 3) | to; },
 | 
					 | 
				
			||||||
      TRANSITIONS = {};
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  // init transitions
 | 
					 | 
				
			||||||
  TRANSITIONS[T( FOCUS, BLUR )]      = function(base) { base.fadeTo(1.0); };
 | 
					 | 
				
			||||||
  TRANSITIONS[T( NOT_EMPTY, BLUR )]  = function(base) { base.$label.css({opacity: 1.0}).show(); base.emptied(true); };
 | 
					 | 
				
			||||||
  TRANSITIONS[T( BLUR, FOCUS )]      = function(base) { base.fadeTo(base.options.fadeOpacity); };
 | 
					 | 
				
			||||||
  TRANSITIONS[T( NOT_EMPTY, FOCUS )] = function(base) { base.$label.css({opacity: base.options.fadeOpacity}).show(); base.emptied(true); };
 | 
					 | 
				
			||||||
  TRANSITIONS[T( BLUR, NOT_EMPTY )]  = function(base) { base.$label.hide(); base.emptied(false); };
 | 
					 | 
				
			||||||
  TRANSITIONS[T( FOCUS, NOT_EMPTY )] = TRANSITIONS[T( BLUR, NOT_EMPTY )];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $.InFieldLabels = function (label, field, options) {
 | 
					 | 
				
			||||||
    // To avoid scope issues, use 'base' instead of 'this'
 | 
					 | 
				
			||||||
    // to reference this class from internal events and functions.
 | 
					 | 
				
			||||||
    var base = this;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
    // Access to jQuery and DOM versions of each element
 | 
					 | 
				
			||||||
    base.$label = $(label);
 | 
					 | 
				
			||||||
    base.label  = label;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.$field = $(field);
 | 
					 | 
				
			||||||
    base.field  = field;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.$label.data('InFieldLabels', base);
 | 
					 | 
				
			||||||
    base.state = BLUR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.init = function () {
 | 
					 | 
				
			||||||
      // Merge supplied options with default options
 | 
					 | 
				
			||||||
      base.options = $.extend({}, $.InFieldLabels.defaultOptions, options);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (base.options.labelClass) {
 | 
					 | 
				
			||||||
        base.$label.addClass(base.options.labelClass);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (base.options.disableAutocomplete) {
 | 
					 | 
				
			||||||
        base.$field.attr('autocomplete', 'off');
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      base.$field
 | 
					 | 
				
			||||||
          .bind('blur focus change keyup.infield cut', base.updateState)
 | 
					 | 
				
			||||||
          // paste cannot be empty
 | 
					 | 
				
			||||||
          .bind('paste', function(e){ base.setState(NOT_EMPTY); });
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      base.updateState();
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.emptied = function(empty) {
 | 
					 | 
				
			||||||
      if (!base.options.emptyWatch) {
 | 
					 | 
				
			||||||
        if (empty) {
 | 
					 | 
				
			||||||
          // namespace ensures we unbind only our handler
 | 
					 | 
				
			||||||
          base.$field.bind('keyup.infield', base.updateState);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          // save CPU but won't detect empty until blur
 | 
					 | 
				
			||||||
          base.$field.unbind('keyup.infield', base.updateState);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.fadeTo = function (opacity) {
 | 
					 | 
				
			||||||
      if (!base.options.fadeDuration) {
 | 
					 | 
				
			||||||
        base.$label.css({ opacity: opacity });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.updateState = function (e, nl) {
 | 
					 | 
				
			||||||
      var state = NOT_EMPTY;
 | 
					 | 
				
			||||||
      if (base.field.value === '') {
 | 
					 | 
				
			||||||
        var focus = e && e.type;
 | 
					 | 
				
			||||||
        if (focus === 'focus' || focus === 'keyup') {
 | 
					 | 
				
			||||||
          focus = true;
 | 
					 | 
				
			||||||
        } else if (focus === 'blur' || focus === 'change') {
 | 
					 | 
				
			||||||
          focus = false;
 | 
					 | 
				
			||||||
        } else {  // last resort because slowest
 | 
					 | 
				
			||||||
          focus = base.$field.is(':focus');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        state = focus ? FOCUS : BLUR;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      base.setState(state, nl);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    base.setState = function (state, nl) {
 | 
					 | 
				
			||||||
      if (state === base.state) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var transition = TRANSITIONS[T(base.state, state)];
 | 
					 | 
				
			||||||
      if (typeof transition === 'function') {
 | 
					 | 
				
			||||||
        transition(base);
 | 
					 | 
				
			||||||
        base.state = state;
 | 
					 | 
				
			||||||
      } else { // unkown transition - shouldn't happen
 | 
					 | 
				
			||||||
        // nl avoids looping
 | 
					 | 
				
			||||||
        nl || base.updateState(null, true);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Run the initialization method
 | 
					 | 
				
			||||||
    base.init();
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $.InFieldLabels.defaultOptions = {
 | 
					 | 
				
			||||||
    emptyWatch: true, // Keep watching the field as the user types (slower but brings back the label immediately when the field is emptied)
 | 
					 | 
				
			||||||
    disableAutocomplete: true, // Disable autocomplete on the matched fields
 | 
					 | 
				
			||||||
    fadeOpacity: 0.5, // Once a field has focus, how transparent should the label be
 | 
					 | 
				
			||||||
    fadeDuration: 300, // How long should it take to animate from 1.0 opacity to the fadeOpacity
 | 
					 | 
				
			||||||
    labelClass: 'in-field' // CSS class to apply to the label when it gets in-field
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  $.fn.inFieldLabels = function (options) {
 | 
					 | 
				
			||||||
    return this.each(function () {
 | 
					 | 
				
			||||||
      if (this.tagName !== 'LABEL') {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      // Find input or textarea based on for= attribute
 | 
					 | 
				
			||||||
      // The for attribute on the label must contain the ID
 | 
					 | 
				
			||||||
      // of the input or textarea element
 | 
					 | 
				
			||||||
      var for_attr = this.getAttribute('for') || this.htmlFor,
 | 
					 | 
				
			||||||
          field, valid = true;
 | 
					 | 
				
			||||||
      if (!for_attr) {
 | 
					 | 
				
			||||||
        return; // Nothing to attach, since the for field wasn't used
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Find the referenced input or textarea element
 | 
					 | 
				
			||||||
      field = document.getElementById(for_attr);
 | 
					 | 
				
			||||||
      if (!field) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (field.tagName === 'INPUT') {
 | 
					 | 
				
			||||||
        valid = INPUT_TYPE.test(field.type.toLowerCase());
 | 
					 | 
				
			||||||
      } else if (field.tagName !== 'TEXTAREA') {
 | 
					 | 
				
			||||||
        valid = false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      valid = valid && !field.getAttribute('placeholder');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!valid) {
 | 
					 | 
				
			||||||
        return; // Again, nothing to attach
 | 
					 | 
				
			||||||
      } 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Only create object for input[text], input[password], or textarea
 | 
					 | 
				
			||||||
      (new $.InFieldLabels(this, field, options));
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}(jQuery));
 | 
					 | 
				
			||||||
							
								
								
									
										7382
									
								
								js/extlib/jquery.js
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
    json2.js
 | 
					    json2.js
 | 
				
			||||||
    2013-05-26
 | 
					    2015-02-25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Public Domain.
 | 
					    Public Domain.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,7 +48,9 @@
 | 
				
			|||||||
                Date.prototype.toJSON = function (key) {
 | 
					                Date.prototype.toJSON = function (key) {
 | 
				
			||||||
                    function f(n) {
 | 
					                    function f(n) {
 | 
				
			||||||
                        // Format integers to have at least two digits.
 | 
					                        // Format integers to have at least two digits.
 | 
				
			||||||
                        return n < 10 ? '0' + n : n;
 | 
					                        return n < 10 
 | 
				
			||||||
 | 
					                        ? '0' + n 
 | 
				
			||||||
 | 
					                        : n;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return this.getUTCFullYear()   + '-' +
 | 
					                    return this.getUTCFullYear()   + '-' +
 | 
				
			||||||
@@ -146,10 +148,12 @@
 | 
				
			|||||||
    redistribute.
 | 
					    redistribute.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*jslint evil: true, regexp: true */
 | 
					/*jslint 
 | 
				
			||||||
 | 
					    eval, for, this 
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
 | 
					/*property
 | 
				
			||||||
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
 | 
					    JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
 | 
				
			||||||
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
 | 
					    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
 | 
				
			||||||
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
 | 
					    lastIndex, length, parse, prototype, push, replace, slice, stringify,
 | 
				
			||||||
    test, toJSON, toString, valueOf
 | 
					    test, toJSON, toString, valueOf
 | 
				
			||||||
@@ -168,7 +172,13 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function f(n) {
 | 
					    function f(n) {
 | 
				
			||||||
        // Format integers to have at least two digits.
 | 
					        // Format integers to have at least two digits.
 | 
				
			||||||
        return n < 10 ? '0' + n : n;
 | 
					        return n < 10 
 | 
				
			||||||
 | 
					        ? '0' + n 
 | 
				
			||||||
 | 
					        : n;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    function this_value() {
 | 
				
			||||||
 | 
					        return this.valueOf();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (typeof Date.prototype.toJSON !== 'function') {
 | 
					    if (typeof Date.prototype.toJSON !== 'function') {
 | 
				
			||||||
@@ -185,26 +195,16 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
            : null;
 | 
					            : null;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        String.prototype.toJSON      =
 | 
					        Boolean.prototype.toJSON = this_value;
 | 
				
			||||||
            Number.prototype.toJSON  =
 | 
					        Number.prototype.toJSON = this_value;
 | 
				
			||||||
            Boolean.prototype.toJSON = function () {
 | 
					        String.prototype.toJSON = this_value;
 | 
				
			||||||
                return this.valueOf();
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 | 
					    var cx,
 | 
				
			||||||
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 | 
					        escapable,
 | 
				
			||||||
        gap,
 | 
					        gap,
 | 
				
			||||||
        indent,
 | 
					        indent,
 | 
				
			||||||
        meta = {    // table of character substitutions
 | 
					        meta,
 | 
				
			||||||
            '\b': '\\b',
 | 
					 | 
				
			||||||
            '\t': '\\t',
 | 
					 | 
				
			||||||
            '\n': '\\n',
 | 
					 | 
				
			||||||
            '\f': '\\f',
 | 
					 | 
				
			||||||
            '\r': '\\r',
 | 
					 | 
				
			||||||
            '"' : '\\"',
 | 
					 | 
				
			||||||
            '\\': '\\\\'
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        rep;
 | 
					        rep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -216,12 +216,14 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
// sequences.
 | 
					// sequences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        escapable.lastIndex = 0;
 | 
					        escapable.lastIndex = 0;
 | 
				
			||||||
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
 | 
					        return escapable.test(string) 
 | 
				
			||||||
 | 
					        ? '"' + string.replace(escapable, function (a) {
 | 
				
			||||||
            var c = meta[a];
 | 
					            var c = meta[a];
 | 
				
			||||||
            return typeof c === 'string'
 | 
					            return typeof c === 'string'
 | 
				
			||||||
            ? c
 | 
					            ? c
 | 
				
			||||||
            : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 | 
					            : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 | 
				
			||||||
        }) + '"' : '"' + string + '"';
 | 
					        }) + '"' 
 | 
				
			||||||
 | 
					        : '"' + string + '"';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -261,7 +263,9 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
 | 
					// JSON numbers must be finite. Encode non-finite numbers as null.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return isFinite(value) ? String(value) : 'null';
 | 
					            return isFinite(value) 
 | 
				
			||||||
 | 
					            ? String(value) 
 | 
				
			||||||
 | 
					            : 'null';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 'boolean':
 | 
					        case 'boolean':
 | 
				
			||||||
        case 'null':
 | 
					        case 'null':
 | 
				
			||||||
@@ -322,7 +326,11 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
                        k = rep[i];
 | 
					                        k = rep[i];
 | 
				
			||||||
                        v = str(k, value);
 | 
					                        v = str(k, value);
 | 
				
			||||||
                        if (v) {
 | 
					                        if (v) {
 | 
				
			||||||
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
 | 
					                            partial.push(quote(k) + (
 | 
				
			||||||
 | 
					                                gap 
 | 
				
			||||||
 | 
					                                ? ': ' 
 | 
				
			||||||
 | 
					                                : ':'
 | 
				
			||||||
 | 
					                            ) + v);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -334,7 +342,11 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
 | 
					                    if (Object.prototype.hasOwnProperty.call(value, k)) {
 | 
				
			||||||
                        v = str(k, value);
 | 
					                        v = str(k, value);
 | 
				
			||||||
                        if (v) {
 | 
					                        if (v) {
 | 
				
			||||||
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
 | 
					                            partial.push(quote(k) + (
 | 
				
			||||||
 | 
					                                gap 
 | 
				
			||||||
 | 
					                                ? ': ' 
 | 
				
			||||||
 | 
					                                : ':'
 | 
				
			||||||
 | 
					                            ) + v);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -356,6 +368,16 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
// If the JSON object does not yet have a stringify method, give it one.
 | 
					// If the JSON object does not yet have a stringify method, give it one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (typeof JSON.stringify !== 'function') {
 | 
					    if (typeof JSON.stringify !== 'function') {
 | 
				
			||||||
 | 
					        escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
 | 
				
			||||||
 | 
					        meta = {    // table of character substitutions
 | 
				
			||||||
 | 
					            '\b': '\\b',
 | 
				
			||||||
 | 
					            '\t': '\\t',
 | 
				
			||||||
 | 
					            '\n': '\\n',
 | 
				
			||||||
 | 
					            '\f': '\\f',
 | 
				
			||||||
 | 
					            '\r': '\\r',
 | 
				
			||||||
 | 
					            '"': '\\"',
 | 
				
			||||||
 | 
					            '\\': '\\\\'
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        JSON.stringify = function (value, replacer, space) {
 | 
					        JSON.stringify = function (value, replacer, space) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The stringify method takes a value and an optional replacer, and an optional
 | 
					// The stringify method takes a value and an optional replacer, and an optional
 | 
				
			||||||
@@ -403,6 +425,7 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
// If the JSON object does not yet have a parse method, give it one.
 | 
					// If the JSON object does not yet have a parse method, give it one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (typeof JSON.parse !== 'function') {
 | 
					    if (typeof JSON.parse !== 'function') {
 | 
				
			||||||
 | 
					        cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
 | 
				
			||||||
        JSON.parse = function (text, reviver) {
 | 
					        JSON.parse = function (text, reviver) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The parse method takes a text and an optional reviver function, and returns
 | 
					// The parse method takes a text and an optional reviver function, and returns
 | 
				
			||||||
@@ -458,10 +481,13 @@ if (typeof JSON !== 'object') {
 | 
				
			|||||||
// we look to see that the remaining characters are only whitespace or ']' or
 | 
					// we look to see that the remaining characters are only whitespace or ']' or
 | 
				
			||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 | 
					// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (/^[\],:{}\s]*$/
 | 
					            if (
 | 
				
			||||||
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
 | 
					                /^[\],:{}\s]*$/.test(
 | 
				
			||||||
 | 
					                    text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
 | 
				
			||||||
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
 | 
					                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
 | 
				
			||||||
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
 | 
					                        .replace(/(?:^|:|,)(?:\s*\[)+/g, '')
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// In the third stage we use the eval function to compile the text into a
 | 
					// In the third stage we use the eval function to compile the text into a
 | 
				
			||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 | 
					// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										271
									
								
								js/util.js
									
									
									
									
									
								
							
							
						
						@@ -32,7 +32,6 @@ var SN = { // StatusNet
 | 
				
			|||||||
            MaxLength: 140,
 | 
					            MaxLength: 140,
 | 
				
			||||||
            PatternUsername: /^[0-9a-zA-Z\-_.]*$/,
 | 
					            PatternUsername: /^[0-9a-zA-Z\-_.]*$/,
 | 
				
			||||||
            HTTP20x30x: [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307],
 | 
					            HTTP20x30x: [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307],
 | 
				
			||||||
            NoticeFormMaster: null // to be cloned from the one at top
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@@ -58,6 +57,9 @@ var SN = { // StatusNet
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    V: {    // Variables
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Map of localized message strings exported to script from the PHP
 | 
					     * Map of localized message strings exported to script from the PHP
 | 
				
			||||||
     * side via Action::getScriptMessages().
 | 
					     * side via Action::getScriptMessages().
 | 
				
			||||||
@@ -94,12 +96,12 @@ var SN = { // StatusNet
 | 
				
			|||||||
         * @access private
 | 
					         * @access private
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        FormNoticeEnhancements: function (form) {
 | 
					        FormNoticeEnhancements: function (form) {
 | 
				
			||||||
            if (jQuery.data(form[0], 'ElementData') === undefined) {
 | 
					            if ($.data(form[0], 'ElementData') === undefined) {
 | 
				
			||||||
                var MaxLength = form.find('.count').text();
 | 
					                var MaxLength = form.find('.count').text();
 | 
				
			||||||
                if (MaxLength === undefined) {
 | 
					                if (MaxLength === undefined) {
 | 
				
			||||||
                    MaxLength = SN.C.I.MaxLength;
 | 
					                    MaxLength = SN.C.I.MaxLength;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                jQuery.data(form[0], 'ElementData', {MaxLength: MaxLength});
 | 
					                $.data(form[0], 'ElementData', {MaxLength: MaxLength});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SN.U.Counter(form);
 | 
					                SN.U.Counter(form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -122,7 +124,7 @@ var SN = { // StatusNet
 | 
				
			|||||||
                NDT.on('cut', delayedUpdate)
 | 
					                NDT.on('cut', delayedUpdate)
 | 
				
			||||||
                    .on('paste', delayedUpdate);
 | 
					                    .on('paste', delayedUpdate);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                form.find('.count').text(jQuery.data(form[0], 'ElementData').MaxLength);
 | 
					                form.find('.count').text($.data(form[0], 'ElementData').MaxLength);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -143,7 +145,7 @@ var SN = { // StatusNet
 | 
				
			|||||||
        Counter: function (form) {
 | 
					        Counter: function (form) {
 | 
				
			||||||
            SN.C.I.FormNoticeCurrent = form;
 | 
					            SN.C.I.FormNoticeCurrent = form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var MaxLength = jQuery.data(form[0], 'ElementData').MaxLength;
 | 
					            var MaxLength = $.data(form[0], 'ElementData').MaxLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (MaxLength <= 0) {
 | 
					            if (MaxLength <= 0) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
@@ -217,6 +219,18 @@ var SN = { // StatusNet
 | 
				
			|||||||
            return url;
 | 
					            return url;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FormNoticeUniqueID: function (form) {
 | 
				
			||||||
 | 
					            var oldId = form.attr('id');
 | 
				
			||||||
 | 
					            var newId = 'form_notice_' + Math.floor(Math.random()*999999999);
 | 
				
			||||||
 | 
					            var attrs = ['name', 'for', 'id'];
 | 
				
			||||||
 | 
					            for (var key in attrs) {
 | 
				
			||||||
 | 
					                form.find("[" + attrs[key] + "~='" + oldId + "']").each(function () {
 | 
				
			||||||
 | 
					                        var newAttr = $(this).attr(attrs[key]).replace(oldId, newId);
 | 
				
			||||||
 | 
					                        $(this).attr(attrs[key], newAttr);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Grabs form data and submits it asynchronously, with 'ajax=1'
 | 
					         * Grabs form data and submits it asynchronously, with 'ajax=1'
 | 
				
			||||||
         * parameter added to the rest.
 | 
					         * parameter added to the rest.
 | 
				
			||||||
@@ -375,7 +389,7 @@ var SN = { // StatusNet
 | 
				
			|||||||
                        if ($('.' + SN.C.S.Error, response).length > 0) {
 | 
					                        if ($('.' + SN.C.S.Error, response).length > 0) {
 | 
				
			||||||
                            form.append(document._importNode($('.' + SN.C.S.Error, response)[0], true));
 | 
					                            form.append(document._importNode($('.' + SN.C.S.Error, response)[0], true));
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            if (parseInt(xhr.status) === 0 || jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) {
 | 
					                            if (parseInt(xhr.status) === 0 || $.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) {
 | 
				
			||||||
                                form
 | 
					                                form
 | 
				
			||||||
                                    .resetForm()
 | 
					                                    .resetForm()
 | 
				
			||||||
                                    .find('.attach-status').remove();
 | 
					                                    .find('.attach-status').remove();
 | 
				
			||||||
@@ -405,16 +419,14 @@ var SN = { // StatusNet
 | 
				
			|||||||
                            if (replyItem.length > 0) {
 | 
					                            if (replyItem.length > 0) {
 | 
				
			||||||
                                // If this is an inline reply, remove the form...
 | 
					                                // If this is an inline reply, remove the form...
 | 
				
			||||||
                                var list = form.closest('.threaded-replies');
 | 
					                                var list = form.closest('.threaded-replies');
 | 
				
			||||||
                                var placeholder = list.find('.notice-reply-placeholder');
 | 
					 | 
				
			||||||
                                replyItem.remove();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                var id = $(notice).attr('id');
 | 
					                                var id = $(notice).attr('id');
 | 
				
			||||||
                                if ($('#' + id).length == 0) {
 | 
					                                if ($('#' + id).length == 0) {
 | 
				
			||||||
                                    $(notice).insertBefore(placeholder);
 | 
					                                    $(notice).insertBefore(replyItem);
 | 
				
			||||||
                                } // else Realtime came through before us...
 | 
					                                } // else Realtime came through before us...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                // ...and show the placeholder form.
 | 
					                                replyItem.remove();
 | 
				
			||||||
                                placeholder.show();
 | 
					
 | 
				
			||||||
                            } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {
 | 
					                            } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {
 | 
				
			||||||
                                // Not a reply. If on our timeline, show it at the top!
 | 
					                                // Not a reply. If on our timeline, show it at the top!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -578,6 +590,44 @@ var SN = { // StatusNet
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Setup function -- DOES NOT trigger actions immediately.
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * Sets up event handlers on all visible notice's option <a> elements
 | 
				
			||||||
 | 
					         * with the "popup" class so they behave as expected with AJAX.
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * (without javascript the link goes to a page that expects you to verify
 | 
				
			||||||
 | 
					         * the action through a form)
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * @access private
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        NoticeOptionsAjax: function () {
 | 
				
			||||||
 | 
					            $(document).on('click', '.notice-options > a.popup', function (e) {
 | 
				
			||||||
 | 
					                e.preventDefault();
 | 
				
			||||||
 | 
					                var noticeEl = $(this).closest('.notice');
 | 
				
			||||||
 | 
					                $.ajax({
 | 
				
			||||||
 | 
					                    url: $(this).attr('href'),
 | 
				
			||||||
 | 
					                    data: {ajax: 1},
 | 
				
			||||||
 | 
					                    success: function (data, textStatus, xhr) {
 | 
				
			||||||
 | 
					                        SN.U.NoticeOptionPopup(data, noticeEl);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        NoticeOptionPopup: function (data, noticeEl) {
 | 
				
			||||||
 | 
					            title = $('head > title', data).text();
 | 
				
			||||||
 | 
					            body = $('body', data).html();
 | 
				
			||||||
 | 
					            dialog = $(body).dialog({
 | 
				
			||||||
 | 
					                    height: "auto",
 | 
				
			||||||
 | 
					                    width: "auto",
 | 
				
			||||||
 | 
					                    modal: true,
 | 
				
			||||||
 | 
					                    resizable: true,
 | 
				
			||||||
 | 
					                    title: title,
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Setup function -- DOES NOT trigger actions immediately.
 | 
					         * Setup function -- DOES NOT trigger actions immediately.
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
@@ -616,41 +666,18 @@ var SN = { // StatusNet
 | 
				
			|||||||
        NoticeInlineReplyTrigger: function (notice, initialText) {
 | 
					        NoticeInlineReplyTrigger: function (notice, initialText) {
 | 
				
			||||||
            // Find the notice we're replying to...
 | 
					            // Find the notice we're replying to...
 | 
				
			||||||
            var id = $($('.notice_id', notice)[0]).text();
 | 
					            var id = $($('.notice_id', notice)[0]).text();
 | 
				
			||||||
            var replyForm, placeholder;
 | 
					            var replyForm;
 | 
				
			||||||
            var parentNotice = notice;
 | 
					            var parentNotice = notice;
 | 
				
			||||||
            var stripForm = true; // strip a couple things out of reply forms that are inline
 | 
					            var stripForm = true; // strip a couple things out of reply forms that are inline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Find the threaded replies view we'll be adding to...
 | 
					            var list = notice.find('.threaded-replies');
 | 
				
			||||||
            var list = notice.closest('.notices');
 | 
					 | 
				
			||||||
            if (list.closest('.old-school').length) {
 | 
					 | 
				
			||||||
                // We're replying to an old-school conversation thread;
 | 
					 | 
				
			||||||
                // use the old-style ping into the top form.
 | 
					 | 
				
			||||||
                SN.U.switchInputFormTab("status");
 | 
					 | 
				
			||||||
                replyForm = $('#input_form_status').find('form');
 | 
					 | 
				
			||||||
                stripForm = false;
 | 
					 | 
				
			||||||
            } else if (list.hasClass('threaded-replies')) {
 | 
					 | 
				
			||||||
                // We're replying to a reply; use reply form on the end of this list.
 | 
					 | 
				
			||||||
                // We'll add our form at the end of this; grab the root notice.
 | 
					 | 
				
			||||||
                parentNotice = list.closest('.notice');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // See if the form's already open...
 | 
					 | 
				
			||||||
                replyForm = $('.notice-reply-form', list);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // We're replying to a parent notice; pull its threaded list
 | 
					 | 
				
			||||||
                // and we'll add on the end of it. Will add if needed.
 | 
					 | 
				
			||||||
                list = $('ul.threaded-replies', notice);
 | 
					 | 
				
			||||||
            if (list.length == 0) {
 | 
					            if (list.length == 0) {
 | 
				
			||||||
                    SN.U.NoticeInlineReplyPlaceholder(notice);
 | 
					                list = notice.closest('.threaded-replies');
 | 
				
			||||||
                    list = $('ul.threaded-replies', notice);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    placeholder = $('li.notice-reply-placeholder', notice);
 | 
					 | 
				
			||||||
                    if (placeholder.length == 0) {
 | 
					 | 
				
			||||||
                        SN.U.NoticeInlineReplyPlaceholder(notice);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                }
 | 
					            if (list.length == 0) {
 | 
				
			||||||
 | 
					                list = $('<ul class="notices threaded-replies xoxo"></ul>');
 | 
				
			||||||
                // See if the form's already open...
 | 
					                notice.append(list);
 | 
				
			||||||
                replyForm = $('.notice-reply-form', list);
 | 
					                list = notice.find('.threaded-replies');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var nextStep = function () {
 | 
					            var nextStep = function () {
 | 
				
			||||||
@@ -663,6 +690,7 @@ var SN = { // StatusNet
 | 
				
			|||||||
                    replyForm.find('label[for=notice_to]').hide();
 | 
					                    replyForm.find('label[for=notice_to]').hide();
 | 
				
			||||||
                    replyForm.find('label[for=notice_private]').hide();
 | 
					                    replyForm.find('label[for=notice_private]').hide();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                replyItem.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Set focus...
 | 
					                // Set focus...
 | 
				
			||||||
                var text = replyForm.find('textarea');
 | 
					                var text = replyForm.find('textarea');
 | 
				
			||||||
@@ -681,82 +709,64 @@ var SN = { // StatusNet
 | 
				
			|||||||
                    text[0].setSelectionRange(len, len);
 | 
					                    text[0].setSelectionRange(len, len);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            if (replyForm.length > 0) {
 | 
					 | 
				
			||||||
                // Update the existing form...
 | 
					 | 
				
			||||||
                nextStep();
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // Hide the placeholder...
 | 
					 | 
				
			||||||
                placeholder = list.find('li.notice-reply-placeholder').hide();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Create the reply form entry at the end
 | 
					            // Create the reply form entry
 | 
				
			||||||
            var replyItem = $('li.notice-reply', list);
 | 
					            var replyItem = $('li.notice-reply', list);
 | 
				
			||||||
            if (replyItem.length == 0) {
 | 
					            if (replyItem.length == 0) {
 | 
				
			||||||
                replyItem = $('<li class="notice-reply"></li>');
 | 
					                replyItem = $('<li class="notice-reply"></li>');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            replyForm = replyItem.children('form');
 | 
				
			||||||
 | 
					            if (replyForm.length == 0) {
 | 
				
			||||||
 | 
					                // Let's try another trick to avoid fetching by URL
 | 
				
			||||||
 | 
					                var noticeForm = $('#input_form_status > form');
 | 
				
			||||||
 | 
					                if (noticeForm.length == 0) {
 | 
				
			||||||
 | 
					                    // No notice form found on the page, so let's just
 | 
				
			||||||
 | 
					                    // fetch a fresh copy of the notice form over AJAX.
 | 
				
			||||||
 | 
					                    $.ajax({
 | 
				
			||||||
 | 
					                        url: SN.V.urlNewNotice,
 | 
				
			||||||
 | 
					                        data: {ajax: 1, inreplyto: id},
 | 
				
			||||||
 | 
					                        success: function (data, textStatus, xhr) {
 | 
				
			||||||
 | 
					                            var formEl = document._importNode($('form', data)[0], true);
 | 
				
			||||||
 | 
					                            replyForm = $(formEl);
 | 
				
			||||||
 | 
					                            replyItem.append(replyForm);
 | 
				
			||||||
 | 
					                            list.append(replyItem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    var intermediateStep = function (formMaster) {
 | 
					                            SN.Init.NoticeFormSetup(replyForm);
 | 
				
			||||||
                        var formEl = document._importNode(formMaster, true);
 | 
					 | 
				
			||||||
                        replyItem.append(formEl);
 | 
					 | 
				
			||||||
                        list.append(replyItem); // *after* the placeholder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        var form = $(formEl);
 | 
					 | 
				
			||||||
                        replyForm = form;
 | 
					 | 
				
			||||||
                        SN.Init.NoticeFormSetup(form);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            nextStep();
 | 
					                            nextStep();
 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
                    if (SN.C.I.NoticeFormMaster) {
 | 
					 | 
				
			||||||
                        // We've already saved a master copy of the form.
 | 
					 | 
				
			||||||
                        // Clone it in!
 | 
					 | 
				
			||||||
                        intermediateStep(SN.C.I.NoticeFormMaster);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        // Fetch a fresh copy of the notice form over AJAX.
 | 
					 | 
				
			||||||
                        // Warning: this can have a delay, which looks bad.
 | 
					 | 
				
			||||||
                        // @fixme this fallback may or may not work
 | 
					 | 
				
			||||||
                        var url = $('#form_notice').attr('action');
 | 
					 | 
				
			||||||
                        $.get(url, {ajax: 1}, function (data, textStatus, xhr) {
 | 
					 | 
				
			||||||
                            intermediateStep($('form', data)[0]);
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
        NoticeInlineReplyPlaceholder: function (notice) {
 | 
					                    // We do everything relevant in 'success' above
 | 
				
			||||||
            var list = notice.find('ul.threaded-replies');
 | 
					                    return;
 | 
				
			||||||
            if (list.length == 0) {
 | 
					 | 
				
			||||||
                list = $('<ul class="notices threaded-replies xoxo"></ul>');
 | 
					 | 
				
			||||||
                notice.append(list);
 | 
					 | 
				
			||||||
                list = notice.find('ul.threaded-replies');
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            var placeholder = $('<li class="notice-reply-placeholder">' +
 | 
					                replyForm = noticeForm.clone();
 | 
				
			||||||
                                    '<input class="placeholder" />' +
 | 
					                SN.Init.NoticeFormSetup(replyForm);
 | 
				
			||||||
                                '</li>');
 | 
					                replyItem.append(replyForm);
 | 
				
			||||||
            placeholder.find('input')
 | 
					                list.append(replyItem);
 | 
				
			||||||
                .val(SN.msg('reply_placeholder'));
 | 
					            }
 | 
				
			||||||
            list.append(placeholder);
 | 
					            // replyForm is set, we're not fetching by URL...
 | 
				
			||||||
 | 
					            // Next setp is to configure in-reply-to etc.
 | 
				
			||||||
 | 
					            nextStep();
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Setup function -- DOES NOT apply immediately.
 | 
					         * Setup function -- DOES NOT apply immediately.
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * Sets up event handlers for inline reply mini-form placeholders.
 | 
					 | 
				
			||||||
         * Uses 'on' rather than 'live' or 'bind', so applies to future as well as present items.
 | 
					         * Uses 'on' rather than 'live' or 'bind', so applies to future as well as present items.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        NoticeInlineReplySetup: function () {
 | 
					        NoticeInlineReplySetup: function () {
 | 
				
			||||||
            $('li.notice-reply-placeholder input')
 | 
					            // Expand conversation links
 | 
				
			||||||
                .on('focus', function () {
 | 
					 | 
				
			||||||
                    var notice = $(this).closest('li.notice');
 | 
					 | 
				
			||||||
                    SN.U.NoticeInlineReplyTrigger(notice);
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            $(document).on('click', 'li.notice-reply-comments a', function () {
 | 
					            $(document).on('click', 'li.notice-reply-comments a', function () {
 | 
				
			||||||
                    var url = $(this).attr('href');
 | 
					                    var url = $(this).attr('href');
 | 
				
			||||||
                    var area = $(this).closest('.threaded-replies');
 | 
					                    var area = $(this).closest('.threaded-replies');
 | 
				
			||||||
                    $.get(url, {ajax: 1}, function (data, textStatus, xhr) {
 | 
					                    $.ajax({
 | 
				
			||||||
 | 
					                        url: url,
 | 
				
			||||||
 | 
					                        data: {ajax: 1},
 | 
				
			||||||
 | 
					                        success: function (data, textStatus, xhr) {
 | 
				
			||||||
                            var replies = $('.threaded-replies', data);
 | 
					                            var replies = $('.threaded-replies', data);
 | 
				
			||||||
                            if (replies.length) {
 | 
					                            if (replies.length) {
 | 
				
			||||||
                                area.replaceWith(document._importNode(replies[0], true));
 | 
					                                area.replaceWith(document._importNode(replies[0], true));
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@@ -1043,7 +1053,7 @@ var SN = { // StatusNet
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            function removeNoticeDataGeo(error) {
 | 
					            function removeNoticeDataGeo(error) {
 | 
				
			||||||
                label
 | 
					                label
 | 
				
			||||||
                    .attr('title', jQuery.trim(label.text()))
 | 
					                    .attr('title', $.trim(label.text()))
 | 
				
			||||||
                    .removeClass('checked');
 | 
					                    .removeClass('checked');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                form.find('[name=lat]').val('');
 | 
					                form.find('[name=lat]').val('');
 | 
				
			||||||
@@ -1460,16 +1470,13 @@ var SN = { // StatusNet
 | 
				
			|||||||
                                // Only close if there's been no edit.
 | 
					                                // Only close if there's been no edit.
 | 
				
			||||||
                                if (cur == '' || cur == textarea.data('initialText')) {
 | 
					                                if (cur == '' || cur == textarea.data('initialText')) {
 | 
				
			||||||
                                    var parentNotice = replyItem.closest('li.notice');
 | 
					                                    var parentNotice = replyItem.closest('li.notice');
 | 
				
			||||||
                                    replyItem.remove();
 | 
					                                    replyItem.hide();
 | 
				
			||||||
                                    parentNotice.find('li.notice-reply-placeholder').show();
 | 
					                                    parentNotice.find('li.notice-reply-placeholder').show();
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Infield labels for notice form inputs.
 | 
					 | 
				
			||||||
                $('.input_forms fieldset fieldset label').inFieldLabels({ fadeOpacity:0 });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1481,13 +1488,15 @@ var SN = { // StatusNet
 | 
				
			|||||||
         * @param {jQuery} form
 | 
					         * @param {jQuery} form
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        NoticeFormSetup: function (form) {
 | 
					        NoticeFormSetup: function (form) {
 | 
				
			||||||
            if (!form.data('NoticeFormSetup')) {
 | 
					            if (form.data('NoticeFormSetup')) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            SN.U.NoticeLocationAttach(form);
 | 
					            SN.U.NoticeLocationAttach(form);
 | 
				
			||||||
 | 
					            SN.U.FormNoticeUniqueID(form);
 | 
				
			||||||
            SN.U.FormNoticeXHR(form);
 | 
					            SN.U.FormNoticeXHR(form);
 | 
				
			||||||
            SN.U.FormNoticeEnhancements(form);
 | 
					            SN.U.FormNoticeEnhancements(form);
 | 
				
			||||||
            SN.U.NoticeDataAttach(form);
 | 
					            SN.U.NoticeDataAttach(form);
 | 
				
			||||||
            form.data('NoticeFormSetup', true);
 | 
					            form.data('NoticeFormSetup', true);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@@ -1498,13 +1507,10 @@ var SN = { // StatusNet
 | 
				
			|||||||
         */
 | 
					         */
 | 
				
			||||||
        Notices: function () {
 | 
					        Notices: function () {
 | 
				
			||||||
            if ($('body.user_in').length > 0) {
 | 
					            if ($('body.user_in').length > 0) {
 | 
				
			||||||
                var masterForm = $('.form_notice:first');
 | 
					 | 
				
			||||||
                if (masterForm.length > 0) {
 | 
					 | 
				
			||||||
                    SN.C.I.NoticeFormMaster = document._importNode(masterForm[0], true);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                SN.U.NoticeRepeat();
 | 
					                SN.U.NoticeRepeat();
 | 
				
			||||||
                SN.U.NoticeReply();
 | 
					                SN.U.NoticeReply();
 | 
				
			||||||
                SN.U.NoticeInlineReplySetup();
 | 
					                SN.U.NoticeInlineReplySetup();
 | 
				
			||||||
 | 
					                SN.U.NoticeOptionsAjax();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SN.U.NoticeAttachments();
 | 
					            SN.U.NoticeAttachments();
 | 
				
			||||||
@@ -1562,60 +1568,6 @@ var SN = { // StatusNet
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * Called when a people tag edit box is shown in the interface
 | 
					 | 
				
			||||||
         *
 | 
					 | 
				
			||||||
         * - loads the jQuery UI autocomplete plugin
 | 
					 | 
				
			||||||
         * - sets event handlers for tag completion
 | 
					 | 
				
			||||||
         *
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        PeopletagAutocomplete: function (txtBox) {
 | 
					 | 
				
			||||||
            var split = function (val) {
 | 
					 | 
				
			||||||
                return val.split( /\s+/ );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            var extractLast = function (term) {
 | 
					 | 
				
			||||||
                return split(term).pop();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // don't navigate away from the field on tab when selecting an item
 | 
					 | 
				
			||||||
            txtBox.on( "keydown", function ( event ) {
 | 
					 | 
				
			||||||
                if ( event.keyCode === $.ui.keyCode.TAB &&
 | 
					 | 
				
			||||||
                        $(this).data( "autocomplete" ).menu.active ) {
 | 
					 | 
				
			||||||
                    event.preventDefault();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }).autocomplete({
 | 
					 | 
				
			||||||
                minLength: 0,
 | 
					 | 
				
			||||||
                source: function (request, response) {
 | 
					 | 
				
			||||||
                    // delegate back to autocomplete, but extract the last term
 | 
					 | 
				
			||||||
                    response($.ui.autocomplete.filter(
 | 
					 | 
				
			||||||
                        SN.C.PtagACData, extractLast(request.term)));
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                focus: function () {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                select: function (event, ui) {
 | 
					 | 
				
			||||||
                    var terms = split(this.value);
 | 
					 | 
				
			||||||
                    terms.pop();
 | 
					 | 
				
			||||||
                    terms.push(ui.item.value);
 | 
					 | 
				
			||||||
                    terms.push("");
 | 
					 | 
				
			||||||
                    this.value = terms.join(" ");
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }).data('autocomplete')._renderItem = function (ul, item) {
 | 
					 | 
				
			||||||
                    // FIXME: with jQuery UI you cannot have it highlight the match
 | 
					 | 
				
			||||||
                    var _l = '<a class="ptag-ac-line-tag">' + item.tag
 | 
					 | 
				
			||||||
                          + ' <em class="privacy_mode">' + item.mode + '</em>'
 | 
					 | 
				
			||||||
                          + '<span class="freq">' + item.freq + '</span></a>'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return $("<li/>")
 | 
					 | 
				
			||||||
                            .addClass('mode-' + item.mode)
 | 
					 | 
				
			||||||
                            .addClass('ptag-ac-line')
 | 
					 | 
				
			||||||
                            .data("item.autocomplete", item)
 | 
					 | 
				
			||||||
                            .append(_l)
 | 
					 | 
				
			||||||
                            .appendTo(ul);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Run setup for the ajax people tags editor
 | 
					         * Run setup for the ajax people tags editor
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
@@ -1644,7 +1596,6 @@ var SN = { // StatusNet
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        SN.C.PtagACData = data;
 | 
					                        SN.C.PtagACData = data;
 | 
				
			||||||
                        SN.Init.PeopletagAutocomplete(form.find('#tags'));
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,16 +118,18 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
            common_config_set('db', 'database', $mirror);
 | 
					            common_config_set('db', 'database', $mirror);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $status = $this->prepare($args);
 | 
					        if (Event::handle('StartActionExecute', array($this, &$args))) {
 | 
				
			||||||
        if ($status) {
 | 
					            $prepared = $this->prepare($args);
 | 
				
			||||||
 | 
					            if ($prepared) {
 | 
				
			||||||
                $this->handle($args);
 | 
					                $this->handle($args);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                common_debug('Prepare failed for Action.');
 | 
					                common_debug('Prepare failed for Action.');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->flush();
 | 
					        $this->flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Event::handle('EndActionExecute', array($status, $this));
 | 
					        Event::handle('EndActionExecute', array($this));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -156,8 +158,8 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
        $this->action = strtolower($this->trimmed('action'));
 | 
					        $this->action = strtolower($this->trimmed('action'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->ajax || $this->boolean('ajax')) {
 | 
					        if ($this->ajax || $this->boolean('ajax')) {
 | 
				
			||||||
            // check with StatusNet::isAjax()
 | 
					            // check with GNUsocial::isAjax()
 | 
				
			||||||
            StatusNet::setAjax(true);
 | 
					            GNUsocial::setAjax(true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->needLogin) {
 | 
					        if ($this->needLogin) {
 | 
				
			||||||
@@ -206,7 +208,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    function showPage()
 | 
					    function showPage()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (StatusNet::isAjax()) {
 | 
					        if (GNUsocial::isAjax()) {
 | 
				
			||||||
            self::showAjax();
 | 
					            self::showAjax();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -326,7 +328,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // favicon.ico should be HTTPS if the rest of the page is
 | 
					            // favicon.ico should be HTTPS if the rest of the page is
 | 
				
			||||||
            $this->element('link', array('rel' => 'shortcut icon',
 | 
					            $this->element('link', array('rel' => 'shortcut icon',
 | 
				
			||||||
                                         'href' => common_path('favicon.ico', StatusNet::isHTTPS())));
 | 
					                                         'href' => common_path('favicon.ico', GNUsocial::isHTTPS())));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (common_config('site', 'mobile')) {
 | 
					        if (common_config('site', 'mobile')) {
 | 
				
			||||||
@@ -415,8 +417,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
                $this->script('extlib/jquery.form.js');
 | 
					                $this->script('extlib/jquery.form.js');
 | 
				
			||||||
                $this->script('extlib/jquery-ui/jquery-ui.js');
 | 
					                $this->script('extlib/jquery-ui/jquery-ui.js');
 | 
				
			||||||
                $this->script('extlib/jquery.cookie.js');
 | 
					                $this->script('extlib/jquery.cookie.js');
 | 
				
			||||||
                $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/extlib/json2.js', StatusNet::isHTTPS()).'"); }');
 | 
					                $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/extlib/json2.js', GNUsocial::isHTTPS()).'"); }');
 | 
				
			||||||
                $this->script('extlib/jquery.infieldlabel.js');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Event::handle('EndShowJQueryScripts', array($this));
 | 
					                Event::handle('EndShowJQueryScripts', array($this));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -430,6 +431,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
                $this->inlineScript('var _peopletagAC = "' .
 | 
					                $this->inlineScript('var _peopletagAC = "' .
 | 
				
			||||||
                                    common_local_url('peopletagautocomplete') . '";');
 | 
					                                    common_local_url('peopletagautocomplete') . '";');
 | 
				
			||||||
                $this->showScriptMessages();
 | 
					                $this->showScriptMessages();
 | 
				
			||||||
 | 
					                $this->showScriptVariables();
 | 
				
			||||||
                // Anti-framing code to avoid clickjacking attacks in older browsers.
 | 
					                // Anti-framing code to avoid clickjacking attacks in older browsers.
 | 
				
			||||||
                // This will show a blank page if the page is being framed, which is
 | 
					                // This will show a blank page if the page is being framed, which is
 | 
				
			||||||
                // consistent with the behavior of the 'X-Frame-Options: SAMEORIGIN'
 | 
					                // consistent with the behavior of the 'X-Frame-Options: SAMEORIGIN'
 | 
				
			||||||
@@ -460,12 +462,6 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
            // TRANS: Localized tooltip for '...' expansion button on overlong remote messages.
 | 
					            // TRANS: Localized tooltip for '...' expansion button on overlong remote messages.
 | 
				
			||||||
            $messages['showmore_tooltip'] = _m('TOOLTIP', 'Show more');
 | 
					            $messages['showmore_tooltip'] = _m('TOOLTIP', 'Show more');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TRANS: Inline reply form submit button: submits a reply comment.
 | 
					 | 
				
			||||||
            $messages['reply_submit'] = _m('BUTTON', 'Reply');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // TRANS: Placeholder text for inline reply form. Clicking in this box will turn it into a mini notice form.
 | 
					 | 
				
			||||||
            $messages['reply_placeholder'] = _m('Write a reply...');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $messages = array_merge($messages, $this->getScriptMessages());
 | 
					            $messages = array_merge($messages, $this->getScriptMessages());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Event::handle('EndScriptMessages', array($this, &$messages));
 | 
					            Event::handle('EndScriptMessages', array($this, &$messages));
 | 
				
			||||||
@@ -478,6 +474,19 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
        return $messages;
 | 
					        return $messages;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function showScriptVariables()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $vars = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (Event::handle('StartScriptVariables', array($this, &$vars))) {
 | 
				
			||||||
 | 
					            $vars['urlNewNotice'] = common_local_url('newnotice');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!empty($vars)) {
 | 
				
			||||||
 | 
					            $this->inlineScript('SN.V = ' . json_encode($vars));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $vars;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * If the action will need localizable text strings, export them here like so:
 | 
					     * If the action will need localizable text strings, export them here like so:
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -638,7 +647,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
            $this->elementStart('a', array('class' => 'home bookmark',
 | 
					            $this->elementStart('a', array('class' => 'home bookmark',
 | 
				
			||||||
                                           'href' => $url));
 | 
					                                           'href' => $url));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (StatusNet::isHTTPS()) {
 | 
					            if (GNUsocial::isHTTPS()) {
 | 
				
			||||||
                $logoUrl = common_config('site', 'ssllogo');
 | 
					                $logoUrl = common_config('site', 'ssllogo');
 | 
				
			||||||
                if (empty($logoUrl)) {
 | 
					                if (empty($logoUrl)) {
 | 
				
			||||||
                    // if logo is an uploaded file, try to fall back to HTTPS file URL
 | 
					                    // if logo is an uploaded file, try to fall back to HTTPS file URL
 | 
				
			||||||
@@ -1144,7 +1153,7 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
                $image    = common_config('license', 'image');
 | 
					                $image    = common_config('license', 'image');
 | 
				
			||||||
                $sslimage = common_config('license', 'sslimage');
 | 
					                $sslimage = common_config('license', 'sslimage');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (StatusNet::isHTTPS()) {
 | 
					                if (GNUsocial::isHTTPS()) {
 | 
				
			||||||
                    if (!empty($sslimage)) {
 | 
					                    if (!empty($sslimage)) {
 | 
				
			||||||
                        $url = $sslimage;
 | 
					                        $url = $sslimage;
 | 
				
			||||||
                    } else if (preg_match('#^http://i.creativecommons.org/#', $image)) {
 | 
					                    } else if (preg_match('#^http://i.creativecommons.org/#', $image)) {
 | 
				
			||||||
@@ -1354,6 +1363,19 @@ class Action extends HTMLOutputter // lawsuit
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * This is a cheap hack to avoid a bug in DB_DataObject
 | 
				
			||||||
 | 
					     * where '' is non-type-aware compared to 0, which means it
 | 
				
			||||||
 | 
					     * will always be true for values like false and 0 too...
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Upstream bug is::
 | 
				
			||||||
 | 
					     * https://pear.php.net/bugs/bug.php?id=20291
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    function booleanintstring($key, $def=false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->boolean($key, $def) ? '1' : '0';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Integer value of an argument
 | 
					     * Integer value of an argument
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -160,10 +160,11 @@ abstract class ActivityHandlerPlugin extends Plugin
 | 
				
			|||||||
    * @fixme are there any standard options?
 | 
					    * @fixme are there any standard options?
 | 
				
			||||||
    *
 | 
					    *
 | 
				
			||||||
    * @param Activity $activity
 | 
					    * @param Activity $activity
 | 
				
			||||||
    * @param Profile $actor
 | 
					    * @param Notice   $stored       The notice in our database for this certain object
 | 
				
			||||||
    * @param array $options=array()
 | 
					    * @param array $options=array()
 | 
				
			||||||
    *
 | 
					    *
 | 
				
			||||||
    * @return Notice the resulting notice
 | 
					    * @return object    If the verb handling plugin creates an object, it can be returned here (otherwise true)
 | 
				
			||||||
 | 
					    * @throws exception On any error.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    protected function saveObjectFromActivity(Activity $activity, Notice $stored, array $options=array())
 | 
					    protected function saveObjectFromActivity(Activity $activity, Notice $stored, array $options=array())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -174,7 +175,7 @@ abstract class ActivityHandlerPlugin extends Plugin
 | 
				
			|||||||
     * This usually gets called from Notice::saveActivity after a Notice object has been created,
 | 
					     * This usually gets called from Notice::saveActivity after a Notice object has been created,
 | 
				
			||||||
     * so it contains a proper id and a uri for the object to be saved.
 | 
					     * so it contains a proper id and a uri for the object to be saved.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function onStoreActivityObject(Activity $act, Notice $stored, array $options=array(), &$object) {
 | 
					    public function onStoreActivityObject(Activity $act, Notice $stored, array $options, &$object) {
 | 
				
			||||||
        // $this->oldSaveNew is there during a migration period of plugins, to start using
 | 
					        // $this->oldSaveNew is there during a migration period of plugins, to start using
 | 
				
			||||||
        // Notice::saveActivity instead of Notice::saveNew
 | 
					        // Notice::saveActivity instead of Notice::saveNew
 | 
				
			||||||
        if (!$this->isMyActivity($act) || isset($this->oldSaveNew)) {
 | 
					        if (!$this->isMyActivity($act) || isset($this->oldSaveNew)) {
 | 
				
			||||||
@@ -182,7 +183,13 @@ abstract class ActivityHandlerPlugin extends Plugin
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        $object = $this->saveObjectFromActivity($act, $stored, $options);
 | 
					        $object = $this->saveObjectFromActivity($act, $stored, $options);
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 | 
					            // In the future we probably want to use something like ActivityVerb_DataObject for the kind
 | 
				
			||||||
 | 
					            // of objects which are returned from saveObjectFromActivity.
 | 
				
			||||||
 | 
					            if ($object instanceof Managed_DataObject) {
 | 
				
			||||||
 | 
					                // If the verb handling plugin figured out some more attention URIs, add them here to the
 | 
				
			||||||
 | 
					                // original activity. This is only done if a separate object is actually needed to be saved.
 | 
				
			||||||
                $act->context->attention = array_merge($act->context->attention, $object->getAttentionArray());
 | 
					                $act->context->attention = array_merge($act->context->attention, $object->getAttentionArray());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (Exception $e) {
 | 
					        } catch (Exception $e) {
 | 
				
			||||||
            common_debug('WARNING: Could not get attention list from object '.get_class($object).'!');
 | 
					            common_debug('WARNING: Could not get attention list from object '.get_class($object).'!');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -595,7 +602,6 @@ abstract class ActivityHandlerPlugin extends Plugin
 | 
				
			|||||||
        $nli->showNoticeSource();
 | 
					        $nli->showNoticeSource();
 | 
				
			||||||
        $nli->showNoticeLocation();
 | 
					        $nli->showNoticeLocation();
 | 
				
			||||||
        $nli->showPermalink();
 | 
					        $nli->showPermalink();
 | 
				
			||||||
        $nli->showRepeat();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nli->showNoticeOptions();
 | 
					        $nli->showNoticeOptions();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,7 @@ class ActivityImporter extends QueueHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // XXX: don't do this for untrusted input!
 | 
					            // XXX: don't do this for untrusted input!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Subscription::start($otherProfile, $profile);
 | 
					            Subscription::ensureStart($otherProfile, $profile);
 | 
				
			||||||
        } else if (empty($activity->actor)
 | 
					        } else if (empty($activity->actor)
 | 
				
			||||||
                   || $activity->actor->id == $author->id) {
 | 
					                   || $activity->actor->id == $author->id) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,7 +123,7 @@ class ActivityImporter extends QueueHandler
 | 
				
			|||||||
                throw new ClientException(_('Unknown profile.'));
 | 
					                throw new ClientException(_('Unknown profile.'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Subscription::start($profile, $otherProfile);
 | 
					            Subscription::ensureStart($profile, $otherProfile);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // TRANS: Client exception thrown when trying to import an event not related to the importing user.
 | 
					            // TRANS: Client exception thrown when trying to import an event not related to the importing user.
 | 
				
			||||||
            throw new Exception(_('This activity seems unrelated to our user.'));
 | 
					            throw new Exception(_('This activity seems unrelated to our user.'));
 | 
				
			||||||
@@ -213,7 +213,7 @@ class ActivityImporter extends QueueHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Get (safe!) HTML and text versions of the content
 | 
					        // Get (safe!) HTML and text versions of the content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $rendered = $this->purify($sourceContent);
 | 
					        $rendered = common_purify($sourceContent);
 | 
				
			||||||
        $content = common_strip_html($rendered);
 | 
					        $content = common_strip_html($rendered);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $shortened = $user->shortenLinks($content);
 | 
					        $shortened = $user->shortenLinks($content);
 | 
				
			||||||
@@ -338,15 +338,4 @@ class ActivityImporter extends QueueHandler
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return array($groups, $replies);
 | 
					        return array($groups, $replies);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function purify($content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $config = array('safe' => 1,
 | 
					 | 
				
			||||||
                        'deny_attribute' => 'id,style,on*');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return htmLawed($content, $config);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,7 +146,7 @@ class ActivityMover extends QueueHandler
 | 
				
			|||||||
                               "Changing sub to {$act->objects[0]->id}".
 | 
					                               "Changing sub to {$act->objects[0]->id}".
 | 
				
			||||||
                               "by {$act->actor->id} to {$remote->nickname}.");
 | 
					                               "by {$act->actor->id} to {$remote->nickname}.");
 | 
				
			||||||
                    $otherProfile = $otherUser->getProfile();
 | 
					                    $otherProfile = $otherUser->getProfile();
 | 
				
			||||||
                    Subscription::start($otherProfile, $remote);
 | 
					                    Subscription::ensureStart($otherProfile, $remote);
 | 
				
			||||||
                    Subscription::cancel($otherProfile, $user->getProfile());
 | 
					                    Subscription::cancel($otherProfile, $user->getProfile());
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    $this->log(LOG_NOTICE,
 | 
					                    $this->log(LOG_NOTICE,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -512,11 +512,11 @@ class ActivityObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            switch (self::canonicalType($object->type)) {
 | 
					            switch (self::canonicalType($object->type)) {
 | 
				
			||||||
            case 'image':
 | 
					            case 'image':
 | 
				
			||||||
                $object->largerImage = $file->url;
 | 
					                $object->largerImage = $file->getUrl();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 'video':
 | 
					            case 'video':
 | 
				
			||||||
            case 'audio':
 | 
					            case 'audio':
 | 
				
			||||||
                $object->stream = $file->url;
 | 
					                $object->stream = $file->getUrl();
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -861,7 +861,7 @@ class ActivityObject
 | 
				
			|||||||
                if (is_string($this->thumbnail)) {
 | 
					                if (is_string($this->thumbnail)) {
 | 
				
			||||||
                    $object['image'] = array('url' => $this->thumbnail);
 | 
					                    $object['image'] = array('url' => $this->thumbnail);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    $object['image'] = array('url' => $this->thumbnail->url);
 | 
					                    $object['image'] = array('url' => $this->thumbnail->getUrl());
 | 
				
			||||||
                    if ($this->thumbnail->width) {
 | 
					                    if ($this->thumbnail->width) {
 | 
				
			||||||
                        $object['image']['width'] = $this->thumbnail->width;
 | 
					                        $object['image']['width'] = $this->thumbnail->width;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,7 @@ class ActivityVerb
 | 
				
			|||||||
    const SHARE    = 'http://activitystrea.ms/schema/1.0/share';
 | 
					    const SHARE    = 'http://activitystrea.ms/schema/1.0/share';
 | 
				
			||||||
    const SAVE     = 'http://activitystrea.ms/schema/1.0/save';
 | 
					    const SAVE     = 'http://activitystrea.ms/schema/1.0/save';
 | 
				
			||||||
    const FAVORITE = 'http://activitystrea.ms/schema/1.0/favorite';
 | 
					    const FAVORITE = 'http://activitystrea.ms/schema/1.0/favorite';
 | 
				
			||||||
 | 
					    const LIKE     = 'http://activitystrea.ms/schema/1.0/like'; // This is a synonym of favorite
 | 
				
			||||||
    const PLAY     = 'http://activitystrea.ms/schema/1.0/play';
 | 
					    const PLAY     = 'http://activitystrea.ms/schema/1.0/play';
 | 
				
			||||||
    const FOLLOW   = 'http://activitystrea.ms/schema/1.0/follow';
 | 
					    const FOLLOW   = 'http://activitystrea.ms/schema/1.0/follow';
 | 
				
			||||||
    const FRIEND   = 'http://activitystrea.ms/schema/1.0/make-friend';
 | 
					    const FRIEND   = 'http://activitystrea.ms/schema/1.0/make-friend';
 | 
				
			||||||
@@ -56,7 +57,8 @@ class ActivityVerb
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Custom OStatus verbs for the flipside until they're standardized
 | 
					    // Custom OStatus verbs for the flipside until they're standardized
 | 
				
			||||||
    const DELETE     = 'http://ostatus.org/schema/1.0/unfollow';
 | 
					    const DELETE     = 'http://ostatus.org/schema/1.0/unfollow';
 | 
				
			||||||
    const UNFAVORITE = 'http://ostatus.org/schema/1.0/unfavorite';
 | 
					    const UNFAVORITE = 'http://activitystrea.ms/schema/1.0/unfavorite';
 | 
				
			||||||
 | 
					    const UNLIKE     = 'http://activitystrea.ms/schema/1.0/unlike'; // This is a synonym of unfavorite
 | 
				
			||||||
    const UNFOLLOW   = 'http://ostatus.org/schema/1.0/unfollow';
 | 
					    const UNFOLLOW   = 'http://ostatus.org/schema/1.0/unfollow';
 | 
				
			||||||
    const LEAVE      = 'http://ostatus.org/schema/1.0/leave';
 | 
					    const LEAVE      = 'http://ostatus.org/schema/1.0/leave';
 | 
				
			||||||
    const UNTAG      = 'http://ostatus.org/schema/1.0/untag';
 | 
					    const UNTAG      = 'http://ostatus.org/schema/1.0/untag';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,24 +59,8 @@ class AdminPanelNav extends Menu
 | 
				
			|||||||
        $nickname = $user->nickname;
 | 
					        $nickname = $user->nickname;
 | 
				
			||||||
        $name = $user->getProfile()->getBestName();
 | 
					        $name = $user->getProfile()->getBestName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Stub section w/ home link
 | 
					        $stub = new HomeStubNav($this->action);
 | 
				
			||||||
        $this->action->elementStart('ul');
 | 
					        $this->submenu(_m('MENU','Home'), $stub);
 | 
				
			||||||
        $this->action->elementStart('li');
 | 
					 | 
				
			||||||
        // TRANS: Header in administrator navigation panel.
 | 
					 | 
				
			||||||
        $this->action->element('h3', null, _m('HEADER','Home'));
 | 
					 | 
				
			||||||
        $this->action->elementStart('ul', 'nav');
 | 
					 | 
				
			||||||
        $this->out->menuItem(common_local_url('all', array('nickname' =>
 | 
					 | 
				
			||||||
                                                           $nickname)),
 | 
					 | 
				
			||||||
                             // TRANS: Menu item in administrator navigation panel.
 | 
					 | 
				
			||||||
                             _m('MENU','Home'),
 | 
					 | 
				
			||||||
                             // TRANS: Menu item title in administrator navigation panel.
 | 
					 | 
				
			||||||
                             // TRANS: %s is a username.
 | 
					 | 
				
			||||||
                             sprintf(_('%s and friends'), $name),
 | 
					 | 
				
			||||||
                             $this->action == 'all', 'nav_timeline_personal');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->action->elementEnd('ul');
 | 
					 | 
				
			||||||
        $this->action->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->action->elementEnd('ul');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->action->elementStart('ul');
 | 
					        $this->action->elementStart('ul');
 | 
				
			||||||
        $this->action->elementStart('li');
 | 
					        $this->action->elementStart('li');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,7 +144,7 @@ class ApiAction extends Action
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    protected function prepare(array $args=array())
 | 
					    protected function prepare(array $args=array())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        StatusNet::setApi(true); // reduce exception reports to aid in debugging
 | 
					        GNUsocial::setApi(true); // reduce exception reports to aid in debugging
 | 
				
			||||||
        parent::prepare($args);
 | 
					        parent::prepare($args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->format   = $this->arg('format');
 | 
					        $this->format   = $this->arg('format');
 | 
				
			||||||
@@ -159,7 +159,7 @@ class ApiAction extends Action
 | 
				
			|||||||
        $this->limit    = $this->count + 1;
 | 
					        $this->limit    = $this->count + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($this->arg('since')) {
 | 
					        if ($this->arg('since')) {
 | 
				
			||||||
            header('X-StatusNet-Warning: since parameter is disabled; use since_id');
 | 
					            header('X-GNUsocial-Warning: since parameter is disabled; use since_id');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->source = $this->trimmed('source');
 | 
					        $this->source = $this->trimmed('source');
 | 
				
			||||||
@@ -264,22 +264,20 @@ class ApiAction extends Action
 | 
				
			|||||||
        $twitter_user['statuses_count'] = $profile->noticeCount();
 | 
					        $twitter_user['statuses_count'] = $profile->noticeCount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Is the requesting user following this user?
 | 
					        // Is the requesting user following this user?
 | 
				
			||||||
 | 
					        // These values might actually also mean "unknown". Ambiguity issues?
 | 
				
			||||||
        $twitter_user['following'] = false;
 | 
					        $twitter_user['following'] = false;
 | 
				
			||||||
        $twitter_user['statusnet_blocking'] = false;
 | 
					        $twitter_user['statusnet_blocking'] = false;
 | 
				
			||||||
        $twitter_user['notifications'] = false;
 | 
					        $twitter_user['notifications'] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($this->auth_user)) {
 | 
					        if ($this->scoped instanceof Profile) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
            $twitter_user['following'] = $this->auth_user->isSubscribed($profile);
 | 
					                $sub = Subscription::getSubscription($this->scoped, $profile);
 | 
				
			||||||
            $twitter_user['statusnet_blocking']  = $this->auth_user->hasBlocked($profile);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Notifications on?
 | 
					                // Notifications on?
 | 
				
			||||||
            $sub = Subscription::pkeyGet(array('subscriber' =>
 | 
					                $twitter_user['following'] = true;
 | 
				
			||||||
                                               $this->auth_user->id,
 | 
					                $twitter_user['statusnet_blocking']  = $this->scoped->hasBlocked($profile);
 | 
				
			||||||
                                               'subscribed' => $profile->id));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($sub) {
 | 
					 | 
				
			||||||
                $twitter_user['notifications'] = ($sub->jabber || $sub->sms);
 | 
					                $twitter_user['notifications'] = ($sub->jabber || $sub->sms);
 | 
				
			||||||
 | 
					            } catch (NoResultException $e) {
 | 
				
			||||||
 | 
					                // well, the values are already false...
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -305,6 +303,7 @@ class ApiAction extends Action
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $base = $this->twitterSimpleStatusArray($notice, $include_user);
 | 
					        $base = $this->twitterSimpleStatusArray($notice, $include_user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // FIXME: MOVE TO SHARE PLUGIN
 | 
				
			||||||
        if (!empty($notice->repeat_of)) {
 | 
					        if (!empty($notice->repeat_of)) {
 | 
				
			||||||
            $original = Notice::getKV('id', $notice->repeat_of);
 | 
					            $original = Notice::getKV('id', $notice->repeat_of);
 | 
				
			||||||
            if ($original instanceof Notice) {
 | 
					            if ($original instanceof Notice) {
 | 
				
			||||||
@@ -376,12 +375,6 @@ class ApiAction extends Action
 | 
				
			|||||||
            $twitter_status['geo'] = null;
 | 
					            $twitter_status['geo'] = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!is_null($this->scoped)) {
 | 
					 | 
				
			||||||
            $twitter_status['repeated']  = $this->scoped->hasRepeated($notice);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $twitter_status['repeated'] = false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Enclosures
 | 
					        // Enclosures
 | 
				
			||||||
        $attachments = $notice->attachments();
 | 
					        $attachments = $notice->attachments();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -430,11 +423,11 @@ class ApiAction extends Action
 | 
				
			|||||||
        $twitter_group['nickname'] = $group->nickname;
 | 
					        $twitter_group['nickname'] = $group->nickname;
 | 
				
			||||||
        $twitter_group['fullname'] = $group->fullname;
 | 
					        $twitter_group['fullname'] = $group->fullname;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($this->auth_user)) {
 | 
					        if ($this->scoped instanceof Profile) {
 | 
				
			||||||
            $twitter_group['member'] = $this->auth_user->isMember($group);
 | 
					            $twitter_group['member'] = $this->scoped->isMember($group);
 | 
				
			||||||
            $twitter_group['blocked'] = Group_block::isBlocked(
 | 
					            $twitter_group['blocked'] = Group_block::isBlocked(
 | 
				
			||||||
                $group,
 | 
					                $group,
 | 
				
			||||||
                $this->auth_user->getProfile()
 | 
					                $this->scoped
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -485,8 +478,8 @@ class ApiAction extends Action
 | 
				
			|||||||
        $twitter_list['member_count'] = $list->taggedCount();
 | 
					        $twitter_list['member_count'] = $list->taggedCount();
 | 
				
			||||||
        $twitter_list['uri'] = $list->getUri();
 | 
					        $twitter_list['uri'] = $list->getUri();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($this->auth_user)) {
 | 
					        if ($this->scoped instanceof Profile) {
 | 
				
			||||||
            $twitter_list['following'] = $list->hasSubscriber($this->auth_user);
 | 
					            $twitter_list['following'] = $list->hasSubscriber($this->scoped);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $twitter_list['following'] = false;
 | 
					            $twitter_list['following'] = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -575,37 +568,30 @@ class ApiAction extends Action
 | 
				
			|||||||
        $relationship = array();
 | 
					        $relationship = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $relationship['source'] =
 | 
					        $relationship['source'] =
 | 
				
			||||||
            $this->relationshipDetailsArray($source, $target);
 | 
					            $this->relationshipDetailsArray($source->getProfile(), $target->getProfile());
 | 
				
			||||||
        $relationship['target'] =
 | 
					        $relationship['target'] =
 | 
				
			||||||
            $this->relationshipDetailsArray($target, $source);
 | 
					            $this->relationshipDetailsArray($target->getProfile(), $source->getProfile());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return array('relationship' => $relationship);
 | 
					        return array('relationship' => $relationship);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function relationshipDetailsArray($source, $target)
 | 
					    function relationshipDetailsArray(Profile $source, Profile $target)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $details = array();
 | 
					        $details = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$source_profile = $source->getProfile();
 | 
					        $details['screen_name'] = $source->getNickname();
 | 
				
			||||||
		$target_profile = $target->getProfile();		
 | 
					        $details['followed_by'] = $target->isSubscribed($source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $details['screen_name'] = $source->nickname;
 | 
					        try {
 | 
				
			||||||
        $details['followed_by'] = $target->isSubscribed($source_profile);
 | 
					            $sub = Subscription::getSubscription($source, $target);
 | 
				
			||||||
        $details['following'] = $source->isSubscribed($target_profile);
 | 
					            $details['following'] = true;
 | 
				
			||||||
 | 
					            $details['notifications_enabled'] = ($sub->jabber || $sub->sms);
 | 
				
			||||||
        $notifications = false;
 | 
					        } catch (NoResultException $e) {
 | 
				
			||||||
 | 
					            $details['following'] = false;
 | 
				
			||||||
        if ($source->isSubscribed($target_profile)) {
 | 
					            $details['notifications_enabled'] = false;
 | 
				
			||||||
            $sub = Subscription::pkeyGet(array('subscriber' =>
 | 
					 | 
				
			||||||
                $source->id, 'subscribed' => $target->id));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!empty($sub)) {
 | 
					 | 
				
			||||||
                $notifications = ($sub->jabber || $sub->sms);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $details['notifications_enabled'] = $notifications;
 | 
					        $details['blocking'] = $source->hasBlocked($target);
 | 
				
			||||||
        $details['blocking'] = $source->hasBlocked($target_profile);
 | 
					 | 
				
			||||||
        $details['id'] = intval($source->id);
 | 
					        $details['id'] = intval($source->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $details;
 | 
					        return $details;
 | 
				
			||||||
@@ -655,6 +641,7 @@ class ApiAction extends Action
 | 
				
			|||||||
                $this->showGeoXML($value);
 | 
					                $this->showGeoXML($value);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 'retweeted_status':
 | 
					            case 'retweeted_status':
 | 
				
			||||||
 | 
					                // FIXME: MOVE TO SHARE PLUGIN
 | 
				
			||||||
                $this->showTwitterXmlStatus($value, 'retweeted_status');
 | 
					                $this->showTwitterXmlStatus($value, 'retweeted_status');
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
@@ -788,7 +775,7 @@ class ApiAction extends Action
 | 
				
			|||||||
    function showSingleAtomStatus($notice)
 | 
					    function showSingleAtomStatus($notice)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        header('Content-Type: application/atom+xml; charset=utf-8');
 | 
					        header('Content-Type: application/atom+xml; charset=utf-8');
 | 
				
			||||||
        print $notice->asAtomEntry(true, true, true, $this->auth_user->getProfile());
 | 
					        print $notice->asAtomEntry(true, true, true, $this->scoped);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function show_single_json_status($notice)
 | 
					    function show_single_json_status($notice)
 | 
				
			||||||
@@ -1352,7 +1339,7 @@ class ApiAction extends Action
 | 
				
			|||||||
                return User::getKV('nickname', $nickname);
 | 
					                return User::getKV('nickname', $nickname);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Fall back to trying the currently authenticated user
 | 
					                // Fall back to trying the currently authenticated user
 | 
				
			||||||
                return $this->auth_user;
 | 
					                return $this->scoped->getUser();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else if (self::is_decimal($id)) {
 | 
					        } else if (self::is_decimal($id)) {
 | 
				
			||||||
@@ -1448,7 +1435,7 @@ class ApiAction extends Action
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!empty($list) && $list->private) {
 | 
					            if (!empty($list) && $list->private) {
 | 
				
			||||||
                if ($this->auth_user->id == $list->tagger) {
 | 
					                if ($this->scoped->id == $list->tagger) {
 | 
				
			||||||
                    return $list;
 | 
					                    return $list;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@@ -1516,6 +1503,11 @@ class ApiAction extends Action
 | 
				
			|||||||
            $aargs['id'] = $id;
 | 
					            $aargs['id'] = $id;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->arg('user');
 | 
				
			||||||
 | 
					        if (!empty($user)) {
 | 
				
			||||||
 | 
					            $aargs['user'] = $user;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $tag = $this->arg('tag');
 | 
					        $tag = $this->arg('tag');
 | 
				
			||||||
        if (!empty($tag)) {
 | 
					        if (!empty($tag)) {
 | 
				
			||||||
            $aargs['tag'] = $tag;
 | 
					            $aargs['tag'] = $tag;
 | 
				
			||||||
 
 | 
				
			|||||||