forked from GNUsocial/gnu-social
		
	Merge commit 'origin/0.8.x' into 0.9.x
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -23,4 +23,4 @@ config-*.php | |||||||
| good-config.php | good-config.php | ||||||
| lac08.log | lac08.log | ||||||
| php.log | php.log | ||||||
| config.php.* |  | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								README
									
									
									
									
									
								
							| @@ -964,9 +964,6 @@ sslserver: use an alternate server name for SSL URLs, like | |||||||
| shorturllength: Length of URL at which URLs in a message exceeding 140 | shorturllength: Length of URL at which URLs in a message exceeding 140 | ||||||
|                 characters will be sent to the user's chosen |                 characters will be sent to the user's chosen | ||||||
|                 shortening service. |                 shortening service. | ||||||
| design: a default design (colors and background) for the site. |  | ||||||
|         Sub-items are: backgroundcolor, contentcolor, sidebarcolor, |  | ||||||
|         textcolor, linkcolor, backgroundimage, disposition. |  | ||||||
| dupelimit: minimum time allowed for one person to say the same thing | dupelimit: minimum time allowed for one person to say the same thing | ||||||
|            twice. Default 60s. Anything lower is considered a user |            twice. Default 60s. Anything lower is considered a user | ||||||
|            or UI error. |            or UI error. | ||||||
| @@ -1432,6 +1429,20 @@ notify third-party servers of updates. | |||||||
| notify: an array of URLs for ping endpoints. Default is the empty | notify: an array of URLs for ping endpoints. Default is the empty | ||||||
|         array (no notification). |         array (no notification). | ||||||
|  |  | ||||||
|  | design | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | Default design (colors and background) for the site. Actual appearance | ||||||
|  | depends on the theme.  Null values mean to use the theme defaults. | ||||||
|  |  | ||||||
|  | backgroundcolor: Hex color of the site background. | ||||||
|  | contentcolor: Hex color of the content area background. | ||||||
|  | sidebarcolor: Hex color of the sidebar background. | ||||||
|  | textcolor: Hex color of all non-link text. | ||||||
|  | linkcolor: Hex color of all links. | ||||||
|  | backgroundimage: Image to use for the background. | ||||||
|  | disposition: Flags for whether or not to tile the background image. | ||||||
|  |  | ||||||
| Plugins | Plugins | ||||||
| ======= | ======= | ||||||
|  |  | ||||||
|   | |||||||
| @@ -130,6 +130,7 @@ class ApiAction extends Action | |||||||
|                                 'laconica/wadl', |                                 'laconica/wadl', | ||||||
|                                 'tags/timeline', |                                 'tags/timeline', | ||||||
|                                 'oembed/oembed', |                                 'oembed/oembed', | ||||||
|  |                                 'groups/show', | ||||||
|                                 'groups/timeline'); |                                 'groups/timeline'); | ||||||
|  |  | ||||||
|         static $bareauth = array('statuses/user_timeline', |         static $bareauth = array('statuses/user_timeline', | ||||||
|   | |||||||
| @@ -167,6 +167,8 @@ class ConversationTree extends NoticeList | |||||||
|  |  | ||||||
|     function _buildTree() |     function _buildTree() | ||||||
|     { |     { | ||||||
|  |         $cnt = 0; | ||||||
|  |  | ||||||
|         $this->tree  = array(); |         $this->tree  = array(); | ||||||
|         $this->table = array(); |         $this->table = array(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -229,7 +229,7 @@ class PublicAction extends Action | |||||||
|         // $top->show(); |         // $top->show(); | ||||||
|         $pop = new PopularNoticeSection($this); |         $pop = new PopularNoticeSection($this); | ||||||
|         $pop->show(); |         $pop->show(); | ||||||
|         $gbp = new GroupsByPostsSection($this); |         $gbp = new GroupsByMembersSection($this); | ||||||
|         $gbp->show(); |         $gbp->show(); | ||||||
|         $feat = new FeaturedUsersSection($this); |         $feat = new FeaturedUsersSection($this); | ||||||
|         $feat->show(); |         $feat->show(); | ||||||
|   | |||||||
| @@ -207,32 +207,10 @@ class TwitapifavoritesAction extends TwitterapiAction | |||||||
|         $other = User::staticGet('id', $notice->profile_id); |         $other = User::staticGet('id', $notice->profile_id); | ||||||
|         if ($other && $other->id != $user->id) { |         if ($other && $other->id != $user->id) { | ||||||
|             if ($other->email && $other->emailnotifyfav) { |             if ($other->email && $other->emailnotifyfav) { | ||||||
|                 $this->notify_mail($other, $user, $notice); |                 mail_notify_fave($other, $user, $notice); | ||||||
|             } |             } | ||||||
|             # XXX: notify by IM |             # XXX: notify by IM | ||||||
|             # XXX: notify by SMS |             # XXX: notify by SMS | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     function notify_mail($other, $user, $notice) |  | ||||||
|     { |  | ||||||
|         $profile = $user->getProfile(); |  | ||||||
|         $bestname = $profile->getBestName(); |  | ||||||
|         $subject = sprintf(_('%s added your notice as a favorite'), $bestname); |  | ||||||
|         $body = sprintf(_("%1\$s just added your notice from %2\$s as one of their favorites.\n\n" . |  | ||||||
|                           "In case you forgot, you can see the text of your notice here:\n\n" . |  | ||||||
|                           "%3\$s\n\n" . |  | ||||||
|                           "You can see the list of %1\$s's favorites here:\n\n" . |  | ||||||
|                           "%4\$s\n\n" . |  | ||||||
|                           "Faithfully yours,\n" . |  | ||||||
|                           "%5\$s\n"), |  | ||||||
|                         $bestname, |  | ||||||
|                         common_exact_date($notice->created), |  | ||||||
|                         common_local_url('shownotice', array('notice' => $notice->id)), |  | ||||||
|                         common_local_url('showfavorites', array('nickname' => $user->nickname)), |  | ||||||
|                         common_config('site', 'name')); |  | ||||||
|  |  | ||||||
|         mail_to_user($other, $subject, $body); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -51,6 +51,32 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; | |||||||
|  class TwitapigroupsAction extends TwitterapiAction |  class TwitapigroupsAction extends TwitterapiAction | ||||||
|  { |  { | ||||||
|  |  | ||||||
|  |      function show($args, $apidata) | ||||||
|  |      { | ||||||
|  |          parent::handle($args); | ||||||
|  |  | ||||||
|  |          common_debug("in groups api action"); | ||||||
|  |  | ||||||
|  |          $this->auth_user = $apidata['user']; | ||||||
|  |          $group = $this->get_group($apidata['api_arg'], $apidata); | ||||||
|  |  | ||||||
|  |          if (empty($group)) { | ||||||
|  |              $this->clientError('Not Found', 404, $apidata['content-type']); | ||||||
|  |              return; | ||||||
|  |          } | ||||||
|  |  | ||||||
|  |          switch($apidata['content-type']) { | ||||||
|  |           case 'xml': | ||||||
|  |              $this->show_single_xml_group($group); | ||||||
|  |              break; | ||||||
|  |           case 'json': | ||||||
|  |              $this->show_single_json_group($group); | ||||||
|  |              break; | ||||||
|  |           default: | ||||||
|  |              $this->clientError(_('API method not found!'), $code = 404); | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  |  | ||||||
|      function timeline($args, $apidata) |      function timeline($args, $apidata) | ||||||
|      { |      { | ||||||
|          parent::handle($args); |          parent::handle($args); | ||||||
| @@ -88,8 +114,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; | |||||||
|              $this->show_xml_timeline($notice); |              $this->show_xml_timeline($notice); | ||||||
|              break; |              break; | ||||||
|           case 'rss': |           case 'rss': | ||||||
|              $this->show_rss_timeline($notice, $title, $link, |              $this->show_rss_timeline($notice, $title, $link, $subtitle); | ||||||
|                  $subtitle, $suplink); |  | ||||||
|              break; |              break; | ||||||
|           case 'atom': |           case 'atom': | ||||||
|              if (isset($apidata['api_arg'])) { |              if (isset($apidata['api_arg'])) { | ||||||
| @@ -101,7 +126,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; | |||||||
|                   'api/laconica/groups/timeline.atom'; |                   'api/laconica/groups/timeline.atom'; | ||||||
|              } |              } | ||||||
|              $this->show_atom_timeline($notice, $title, $id, $link, |              $this->show_atom_timeline($notice, $title, $id, $link, | ||||||
|                  $subtitle, $suplink, $selfuri); |                  $subtitle, null, $selfuri); | ||||||
|              break; |              break; | ||||||
|           case 'json': |           case 'json': | ||||||
|              $this->show_json_timeline($notice); |              $this->show_json_timeline($notice); | ||||||
|   | |||||||
| @@ -88,8 +88,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; | |||||||
|              $this->show_xml_timeline($notice); |              $this->show_xml_timeline($notice); | ||||||
|              break; |              break; | ||||||
|           case 'rss': |           case 'rss': | ||||||
|              $this->show_rss_timeline($notice, $title, $link, |              $this->show_rss_timeline($notice, $title, $link, $subtitle); | ||||||
|                  $subtitle, $suplink); |  | ||||||
|              break; |              break; | ||||||
|           case 'atom': |           case 'atom': | ||||||
|              if (isset($apidata['api_arg'])) { |              if (isset($apidata['api_arg'])) { | ||||||
| @@ -101,7 +100,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; | |||||||
|                   'api/laconica/tags/timeline.atom'; |                   'api/laconica/tags/timeline.atom'; | ||||||
|              } |              } | ||||||
|              $this->show_atom_timeline($notice, $title, $id, $link, |              $this->show_atom_timeline($notice, $title, $id, $link, | ||||||
|                  $subtitle, $suplink, $selfuri); |                  $subtitle, null, $selfuri); | ||||||
|              break; |              break; | ||||||
|           case 'json': |           case 'json': | ||||||
|              $this->show_json_timeline($notice); |              $this->show_json_timeline($notice); | ||||||
|   | |||||||
| @@ -55,26 +55,38 @@ class Design extends Memcached_DataObject | |||||||
|  |  | ||||||
|     function showCSS($out) |     function showCSS($out) | ||||||
|     { |     { | ||||||
|         try { |         $css = ''; | ||||||
|  |  | ||||||
|             $bgcolor = new WebColor($this->backgroundcolor); |         $bgcolor = Design::toWebColor($this->backgroundcolor); | ||||||
|             $ccolor  = new WebColor($this->contentcolor); |  | ||||||
|             $sbcolor = new WebColor($this->sidebarcolor); |  | ||||||
|             $tcolor  = new WebColor($this->textcolor); |  | ||||||
|             $lcolor  = new WebColor($this->linkcolor); |  | ||||||
|  |  | ||||||
|         } catch (WebColorException $e) { |         if (!empty($bgcolor)) { | ||||||
|             // This shouldn't happen |             $css .= 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n"; | ||||||
|             common_log(LOG_ERR, "Unable to create color for design $id.", |  | ||||||
|                 __FILE__); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $css  = 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n"; |         $ccolor  = Design::toWebColor($this->contentcolor); | ||||||
|         $css .= '#content, #site_nav_local_views .current a { background-color: #'; |  | ||||||
|         $css .= $ccolor->hexValue() . '} '."\n"; |         if (!empty($ccolor)) { | ||||||
|         $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n"; |             $css .= '#content, #site_nav_local_views .current a { background-color: #'; | ||||||
|         $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n"; |             $css .= $ccolor->hexValue() . '} '."\n"; | ||||||
|         $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n"; |         } | ||||||
|  |  | ||||||
|  |         $sbcolor = Design::toWebColor($this->sidebarcolor); | ||||||
|  |  | ||||||
|  |         if (!empty($sbcolor)) { | ||||||
|  |             $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $tcolor  = Design::toWebColor($this->textcolor); | ||||||
|  |  | ||||||
|  |         if (!empty($tcolor)) { | ||||||
|  |             $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $lcolor  = Design::toWebColor($this->linkcolor); | ||||||
|  |  | ||||||
|  |         if (!empty($lcolor)) { | ||||||
|  |             $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (!empty($this->backgroundimage) && |         if (!empty($this->backgroundimage) && | ||||||
|             $this->disposition & BACKGROUND_ON) { |             $this->disposition & BACKGROUND_ON) { | ||||||
| @@ -88,8 +100,25 @@ class Design extends Memcached_DataObject | |||||||
|                 '); ' . $repeat . ' background-attachment:fixed; }' . "\n"; |                 '); ' . $repeat . ' background-attachment:fixed; }' . "\n"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $out->element('style', array('type' => 'text/css'), $css); |         if (0 != mb_strlen($css)) { | ||||||
|  |             $out->element('style', array('type' => 'text/css'), $css); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static function toWebColor($color) | ||||||
|  |     { | ||||||
|  |         if (is_null($color)) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             return new WebColor($color); | ||||||
|  |         } catch (WebColorException $e) { | ||||||
|  |             // This shouldn't happen | ||||||
|  |             common_log(LOG_ERR, "Unable to create color for design $id.", | ||||||
|  |                 __FILE__); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static function filename($id, $extension, $extra=null) |     static function filename($id, $extension, $extra=null) | ||||||
| @@ -152,4 +181,33 @@ class Design extends Memcached_DataObject | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Return a design object based on the configured site design. | ||||||
|  |      * | ||||||
|  |      * @return Design a singleton design object for the site. | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     static function siteDesign() | ||||||
|  |     { | ||||||
|  |         static $siteDesign = null; | ||||||
|  |  | ||||||
|  |         if (empty($siteDesign)) { | ||||||
|  |  | ||||||
|  |             $siteDesign = new Design(); | ||||||
|  |  | ||||||
|  |             $attrs = array('backgroundcolor', | ||||||
|  |                            'contentcolor', | ||||||
|  |                            'sidebarcolor', | ||||||
|  |                            'textcolor', | ||||||
|  |                            'linkcolor', | ||||||
|  |                            'backgroundimage', | ||||||
|  |                            'disposition'); | ||||||
|  |  | ||||||
|  |             foreach ($attrs as $attr) { | ||||||
|  |                 $siteDesign->$attr = common_config('design', $attr); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $siteDesign; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -93,7 +93,6 @@ class File extends Memcached_DataObject | |||||||
|         if (empty($file)) { |         if (empty($file)) { | ||||||
|             $file_redir = File_redirection::staticGet('url', $given_url); |             $file_redir = File_redirection::staticGet('url', $given_url); | ||||||
|             if (empty($file_redir)) { |             if (empty($file_redir)) { | ||||||
|                 common_debug("processNew() '$given_url' not a known redirect.\n"); |  | ||||||
|                 $redir_data = File_redirection::where($given_url); |                 $redir_data = File_redirection::where($given_url); | ||||||
|                 $redir_url = $redir_data['url']; |                 $redir_url = $redir_data['url']; | ||||||
|                 if ($redir_url === $given_url) { |                 if ($redir_url === $given_url) { | ||||||
| @@ -114,7 +113,9 @@ class File extends Memcached_DataObject | |||||||
|  |  | ||||||
|         if (empty($x)) { |         if (empty($x)) { | ||||||
|             $x = File::staticGet($file_id); |             $x = File::staticGet($file_id); | ||||||
|             if (empty($x)) die('Impossible!'); |             if (empty($x)) { | ||||||
|  |                 throw new ServerException("Robin thinks something is impossible."); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         File_to_post::processNew($file_id, $notice_id); |         File_to_post::processNew($file_id, $notice_id); | ||||||
|   | |||||||
| @@ -121,10 +121,9 @@ class Notice extends Memcached_DataObject | |||||||
|         //this is needed to remove dupes before saving e.g. #hash.tag = #hashtag |         //this is needed to remove dupes before saving e.g. #hash.tag = #hashtag | ||||||
|         $hashtags = array(); |         $hashtags = array(); | ||||||
|         for($i=0; $i<count($match[1]); $i++) { |         for($i=0; $i<count($match[1]); $i++) { | ||||||
|              $hashtags[] = common_canonical_tag($match[1][$i]); |             $hashtags[] = common_canonical_tag($match[1][$i]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   |  | ||||||
|         /* Add them to the database */ |         /* Add them to the database */ | ||||||
|         foreach(array_unique($hashtags) as $hashtag) { |         foreach(array_unique($hashtags) as $hashtag) { | ||||||
|             /* elide characters we don't want in the tag */ |             /* elide characters we don't want in the tag */ | ||||||
| @@ -197,29 +196,30 @@ class Notice extends Memcached_DataObject | |||||||
|             $notice->is_local = $is_local; |             $notice->is_local = $is_local; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		$notice->query('BEGIN'); |  | ||||||
|  |  | ||||||
| 		$notice->reply_to = $reply_to; |  | ||||||
|         if (!empty($created)) { |         if (!empty($created)) { | ||||||
|             $notice->created = $created; |             $notice->created = $created; | ||||||
|         } else { |         } else { | ||||||
|             $notice->created = common_sql_now(); |             $notice->created = common_sql_now(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		$notice->content = $final; | 		$notice->content = $final; | ||||||
| 		$notice->rendered = common_render_content($final, $notice); | 		$notice->rendered = common_render_content($final, $notice); | ||||||
| 		$notice->source = $source; | 		$notice->source = $source; | ||||||
| 		$notice->uri = $uri; | 		$notice->uri = $uri; | ||||||
|  |  | ||||||
|         if (!empty($reply_to)) { | 		$notice->reply_to = self::getReplyTo($reply_to, $profile_id, $source, $final); | ||||||
|             $reply_notice = Notice::staticGet('id', $reply_to); |  | ||||||
|             if (!empty($reply_notice)) { |         if (!empty($notice->reply_to)) { | ||||||
|                 $notice->reply_to = $reply_to; |             $reply = Notice::staticGet('id', $notice->reply_to); | ||||||
|                 $notice->conversation = $reply_notice->conversation; |             $notice->conversation = $reply->conversation; | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (Event::handle('StartNoticeSave', array(&$notice))) { |         if (Event::handle('StartNoticeSave', array(&$notice))) { | ||||||
|  |  | ||||||
|  |             // XXX: some of these functions write to the DB | ||||||
|  |  | ||||||
|  |             $notice->query('BEGIN'); | ||||||
|  |  | ||||||
|             $id = $notice->insert(); |             $id = $notice->insert(); | ||||||
|  |  | ||||||
|             if (!$id) { |             if (!$id) { | ||||||
| @@ -227,18 +227,33 @@ class Notice extends Memcached_DataObject | |||||||
|                 return _('Problem saving notice.'); |                 return _('Problem saving notice.'); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             # Update the URI after the notice is in the database |             // Update ID-dependent columns: URI, conversation | ||||||
|             if (!$uri) { |  | ||||||
|                 $orig = clone($notice); |  | ||||||
|                 $notice->uri = common_notice_uri($notice); |  | ||||||
|  |  | ||||||
|  |             $orig = clone($notice); | ||||||
|  |  | ||||||
|  |             $changed = false; | ||||||
|  |  | ||||||
|  |             if (empty($uri)) { | ||||||
|  |                 $notice->uri = common_notice_uri($notice); | ||||||
|  |                 $changed = true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // If it's not part of a conversation, it's | ||||||
|  |             // the beginning of a new conversation. | ||||||
|  |  | ||||||
|  |             if (empty($notice->conversation)) { | ||||||
|  |                 $notice->conversation = $notice->id; | ||||||
|  |                 $changed = true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if ($changed) { | ||||||
|                 if (!$notice->update($orig)) { |                 if (!$notice->update($orig)) { | ||||||
|                     common_log_db_error($notice, 'UPDATE', __FILE__); |                     common_log_db_error($notice, 'UPDATE', __FILE__); | ||||||
|                     return _('Problem saving notice.'); |                     return _('Problem saving notice.'); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             # XXX: do we need to change this for remote users? |             // XXX: do we need to change this for remote users? | ||||||
|  |  | ||||||
|             $notice->saveReplies(); |             $notice->saveReplies(); | ||||||
|             $notice->saveTags(); |             $notice->saveTags(); | ||||||
| @@ -246,8 +261,13 @@ class Notice extends Memcached_DataObject | |||||||
|             $notice->addToInboxes(); |             $notice->addToInboxes(); | ||||||
|  |  | ||||||
|             $notice->saveUrls(); |             $notice->saveUrls(); | ||||||
|  |  | ||||||
|  |             // FIXME: why do we have to re-render the content? | ||||||
|  |             // Remove this if it's not necessary. | ||||||
|  |  | ||||||
|             $orig2 = clone($notice); |             $orig2 = clone($notice); | ||||||
|     		$notice->rendered = common_render_content($final, $notice); |  | ||||||
|  |             $notice->rendered = common_render_content($final, $notice); | ||||||
|             if (!$notice->update($orig2)) { |             if (!$notice->update($orig2)) { | ||||||
|                 common_log_db_error($notice, 'UPDATE', __FILE__); |                 common_log_db_error($notice, 'UPDATE', __FILE__); | ||||||
|                 return _('Problem saving notice.'); |                 return _('Problem saving notice.'); | ||||||
| @@ -304,9 +324,9 @@ class Notice extends Memcached_DataObject | |||||||
|         $notice->profile_id = $profile_id; |         $notice->profile_id = $profile_id; | ||||||
|         $notice->content = $content; |         $notice->content = $content; | ||||||
|         if (common_config('db','type') == 'pgsql') |         if (common_config('db','type') == 'pgsql') | ||||||
|             $notice->whereAdd('extract(epoch from now() - created) < ' . common_config('site', 'dupelimit')); |           $notice->whereAdd('extract(epoch from now() - created) < ' . common_config('site', 'dupelimit')); | ||||||
|         else |         else | ||||||
|             $notice->whereAdd('now() - created < ' . common_config('site', 'dupelimit')); |           $notice->whereAdd('now() - created < ' . common_config('site', 'dupelimit')); | ||||||
|  |  | ||||||
|         $cnt = $notice->count(); |         $cnt = $notice->count(); | ||||||
|         return ($cnt == 0); |         return ($cnt == 0); | ||||||
| @@ -920,14 +940,14 @@ class Notice extends Memcached_DataObject | |||||||
|     { |     { | ||||||
|         $user = new User(); |         $user = new User(); | ||||||
|  |  | ||||||
| 	if(common_config('db','quote_identifiers')) |         if(common_config('db','quote_identifiers')) | ||||||
| 	    $user_table = '"user"'; |           $user_table = '"user"'; | ||||||
| 	else $user_table = 'user'; |         else $user_table = 'user'; | ||||||
|  |  | ||||||
|         $qry = |         $qry = | ||||||
|           'SELECT id ' . |           'SELECT id ' . | ||||||
| 	  'FROM '. $user_table .' JOIN subscription '. |           'FROM '. $user_table .' JOIN subscription '. | ||||||
| 	  'ON '. $user_table .'.id = subscription.subscriber ' . |           'ON '. $user_table .'.id = subscription.subscriber ' . | ||||||
|           'WHERE subscription.subscribed = %d '; |           'WHERE subscription.subscribed = %d '; | ||||||
|  |  | ||||||
|         $user->query(sprintf($qry, $this->profile_id)); |         $user->query(sprintf($qry, $this->profile_id)); | ||||||
| @@ -1045,16 +1065,6 @@ class Notice extends Memcached_DataObject | |||||||
|             if (!$recipient) { |             if (!$recipient) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             if ($i == 0 && ($recipient->id != $sender->id) && !$this->reply_to) { // Don't save reply to self |  | ||||||
|                 $reply_for = $recipient; |  | ||||||
|                 $recipient_notice = $reply_for->getCurrentNotice(); |  | ||||||
|                 if ($recipient_notice) { |  | ||||||
|                     $orig = clone($this); |  | ||||||
|                     $this->reply_to = $recipient_notice->id; |  | ||||||
|                     $this->conversation = $recipient_notice->conversation; |  | ||||||
|                     $this->update($orig); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             // Don't save replies from blocked profile to local user |             // Don't save replies from blocked profile to local user | ||||||
|             $recipient_user = User::staticGet('id', $recipient->id); |             $recipient_user = User::staticGet('id', $recipient->id); | ||||||
|             if ($recipient_user && $recipient_user->hasBlocked($sender)) { |             if ($recipient_user && $recipient_user->hasBlocked($sender)) { | ||||||
| @@ -1101,14 +1111,6 @@ class Notice extends Memcached_DataObject | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // If it's not a reply, make it the root of a new conversation |  | ||||||
|  |  | ||||||
|         if (empty($this->conversation)) { |  | ||||||
|             $orig = clone($this); |  | ||||||
|             $this->conversation = $this->id; |  | ||||||
|             $this->update($orig); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         foreach (array_keys($replied) as $recipient) { |         foreach (array_keys($replied) as $recipient) { | ||||||
|             $user = User::staticGet('id', $recipient); |             $user = User::staticGet('id', $recipient); | ||||||
|             if ($user) { |             if ($user) { | ||||||
| @@ -1280,4 +1282,76 @@ class Notice extends Memcached_DataObject | |||||||
|  |  | ||||||
|         return $ids; |         return $ids; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Determine which notice, if any, a new notice is in reply to. | ||||||
|  |      * | ||||||
|  |      * For conversation tracking, we try to see where this notice fits | ||||||
|  |      * in the tree. Rough algorithm is: | ||||||
|  |      * | ||||||
|  |      * if (reply_to is set and valid) { | ||||||
|  |      *     return reply_to; | ||||||
|  |      * } else if ((source not API or Web) and (content starts with "T NAME" or "@name ")) { | ||||||
|  |      *     return ID of last notice by initial @name in content; | ||||||
|  |      * } | ||||||
|  |      * | ||||||
|  |      * Note that all @nickname instances will still be used to save "reply" records, | ||||||
|  |      * so the notice shows up in the mentioned users' "replies" tab. | ||||||
|  |      * | ||||||
|  |      * @param integer $reply_to   ID passed in by Web or API | ||||||
|  |      * @param integer $profile_id ID of author | ||||||
|  |      * @param string  $source     Source tag, like 'web' or 'gwibber' | ||||||
|  |      * @param string  $content    Final notice content | ||||||
|  |      * | ||||||
|  |      * @return integer ID of replied-to notice, or null for not a reply. | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     static function getReplyTo($reply_to, $profile_id, $source, $content) | ||||||
|  |     { | ||||||
|  |         static $lb = array('xmpp', 'mail', 'sms', 'omb'); | ||||||
|  |  | ||||||
|  |         // If $reply_to is specified, we check that it exists, and then | ||||||
|  |         // return it if it does | ||||||
|  |  | ||||||
|  |         if (!empty($reply_to)) { | ||||||
|  |             $reply_notice = Notice::staticGet('id', $reply_to); | ||||||
|  |             if (!empty($reply_notice)) { | ||||||
|  |                 return $reply_to; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // If it's not a "low bandwidth" source (one where you can't set | ||||||
|  |         // a reply_to argument), we return. This is mostly web and API | ||||||
|  |         // clients. | ||||||
|  |  | ||||||
|  |         if (!in_array($source, $lb)) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Is there an initial @ or T? | ||||||
|  |  | ||||||
|  |         if (preg_match('/^T ([A-Z0-9]{1,64}) /', $content, $match) || | ||||||
|  |             preg_match('/^@([a-z0-9]{1,64})\s+/', $content, $match)) { | ||||||
|  |             $nickname = common_canonical_nickname($match[1]); | ||||||
|  |         } else { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Figure out who that is. | ||||||
|  |  | ||||||
|  |         $sender = Profile::staticGet('id', $profile_id); | ||||||
|  |         $recipient = common_relative_profile($sender, $nickname, common_sql_now()); | ||||||
|  |  | ||||||
|  |         if (empty($recipient)) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Get their last notice | ||||||
|  |  | ||||||
|  |         $last = $recipient->getCurrentNotice(); | ||||||
|  |  | ||||||
|  |         if (!empty($last)) { | ||||||
|  |             return $last->id; | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -108,11 +108,24 @@ class Session extends Memcached_DataObject | |||||||
|  |  | ||||||
|         $epoch = common_sql_date(time() - $maxlifetime); |         $epoch = common_sql_date(time() - $maxlifetime); | ||||||
|  |  | ||||||
|  |         $ids = array(); | ||||||
|  |  | ||||||
|         $session = new Session(); |         $session = new Session(); | ||||||
|         $session->whereAdd('modified < "'.$epoch.'"'); |         $session->whereAdd('modified < "'.$epoch.'"'); | ||||||
|         $result = $session->delete(DB_DATAOBJECT_WHEREADD_ONLY); |         $session->selectAdd(); | ||||||
|  |         $session->selectAdd('id'); | ||||||
|  |  | ||||||
|         self::logdeb("garbage collection result = $result"); |         $session->find(); | ||||||
|  |  | ||||||
|  |         while ($session->fetch()) { | ||||||
|  |             $ids[] = $session->id; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $session->free(); | ||||||
|  |  | ||||||
|  |         foreach ($ids as $id) { | ||||||
|  |             self::destroy($id); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static function setSaveHandler() |     static function setSaveHandler() | ||||||
|   | |||||||
| @@ -18,14 +18,14 @@ $config['site']['server'] = 'localhost'; | |||||||
| $config['site']['path'] = 'laconica'; | $config['site']['path'] = 'laconica'; | ||||||
| // $config['site']['fancy'] = false; | // $config['site']['fancy'] = false; | ||||||
| // $config['site']['theme'] = 'default'; | // $config['site']['theme'] = 'default'; | ||||||
| // Sets the site's default design values (match it with the values in the theme) | // Sets the site's default design values | ||||||
| // $config['site']['design']['backgroundcolor'] = '#F0F2F5'; | // $config['design']['backgroundcolor'] = '#F0F2F5'; | ||||||
| // $config['site']['design']['contentcolor'] = '#FFFFFF'; | // $config['design']['contentcolor'] = '#FFFFFF'; | ||||||
| // $config['site']['design']['sidebarcolor'] = '#CEE1E9'; | // $config['design']['sidebarcolor'] = '#CEE1E9'; | ||||||
| // $config['site']['design']['textcolor'] = '#000000'; | // $config['design']['textcolor'] = '#000000'; | ||||||
| // $config['site']['design']['linkcolor'] = '#002E6E'; | // $config['design']['linkcolor'] = '#002E6E'; | ||||||
| // $config['site']['design']['backgroundimage'] = null; | // $config['design']['backgroundimage'] = null; | ||||||
| // $config['site']['design']['disposition'] = 1; | // $config['design']['disposition'] = 1; | ||||||
| // To enable the built-in mobile style sheet, defaults to false. | // To enable the built-in mobile style sheet, defaults to false. | ||||||
| // $config['site']['mobile'] = true; | // $config['site']['mobile'] = true; | ||||||
| // For contact email, defaults to $_SERVER["SERVER_ADMIN"] | // For contact email, defaults to $_SERVER["SERVER_ADMIN"] | ||||||
|   | |||||||
							
								
								
									
										108
									
								
								db/074to080_pg.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								db/074to080_pg.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | BEGIN; | ||||||
|  | create sequence design_seq; | ||||||
|  | create table design ( | ||||||
|  |     id bigint default nextval('design_seq') /* comment 'design ID'*/, | ||||||
|  |     backgroundcolor integer /* comment 'main background color'*/ , | ||||||
|  |     contentcolor integer /*comment 'content area background color'*/ , | ||||||
|  |     sidebarcolor integer /*comment 'sidebar background color'*/ , | ||||||
|  |     textcolor integer /*comment 'text color'*/ , | ||||||
|  |     linkcolor integer /*comment 'link color'*/, | ||||||
|  |     backgroundimage varchar(255) /*comment 'background image, if any'*/, | ||||||
|  |     disposition int default 1 /*comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image'*/, | ||||||
|  |     primary key (id) | ||||||
|  | ); | ||||||
|  | alter table "user" | ||||||
|  |      add column design_id integer references design(id); | ||||||
|  | alter table "user" | ||||||
|  |      add column viewdesigns integer default 1; | ||||||
|  |  | ||||||
|  | alter table notice add column | ||||||
|  |      conversation integer references notice (id); | ||||||
|  |  | ||||||
|  | create index notice_conversation_idx on notice(conversation); | ||||||
|  |  | ||||||
|  | alter table foreign_user | ||||||
|  |      alter column id TYPE bigint; | ||||||
|  |       | ||||||
|  | alter table foreign_user alter column id set not null; | ||||||
|  |  | ||||||
|  | alter table foreign_link | ||||||
|  |      alter column foreign_id TYPE bigint; | ||||||
|  |  | ||||||
|  | alter table user_group | ||||||
|  |       add column design_id integer; | ||||||
|  |  | ||||||
|  | /*attachments and URLs stuff */ | ||||||
|  | create sequence file_seq; | ||||||
|  | create table file ( | ||||||
|  |     id bigint default nextval('file_seq') primary key /* comment 'unique identifier' */, | ||||||
|  |     url varchar(255) unique,  | ||||||
|  |     mimetype varchar(50),  | ||||||
|  |     size integer,  | ||||||
|  |     title varchar(255),  | ||||||
|  |     date integer,  | ||||||
|  |     protected integer, | ||||||
|  |     filename text /* comment 'if a local file, name of the file' */, | ||||||
|  |     modified timestamp default CURRENT_TIMESTAMP /* comment 'date this record was modified'*/ | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | create sequence file_oembed_seq; | ||||||
|  | create table file_oembed ( | ||||||
|  |     file_id bigint default nextval('file_oembed_seq') primary key /* comment 'unique identifier' */, | ||||||
|  |     version varchar(20), | ||||||
|  |     type varchar(20), | ||||||
|  |     provider varchar(50), | ||||||
|  |     provider_url varchar(255), | ||||||
|  |     width integer, | ||||||
|  |     height integer, | ||||||
|  |     html text, | ||||||
|  |     title varchar(255), | ||||||
|  |     author_name varchar(50),  | ||||||
|  |     author_url varchar(255),  | ||||||
|  |     url varchar(255)  | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | create sequence file_redirection_seq; | ||||||
|  | create table file_redirection ( | ||||||
|  |     url varchar(255) primary key,  | ||||||
|  |     file_id bigint,  | ||||||
|  |     redirections integer,  | ||||||
|  |     httpcode integer | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | create sequence file_thumbnail_seq; | ||||||
|  | create table file_thumbnail ( | ||||||
|  |     file_id bigint primary key,  | ||||||
|  |     url varchar(255) unique,  | ||||||
|  |     width integer,  | ||||||
|  |     height integer  | ||||||
|  | ); | ||||||
|  | create sequence file_to_post_seq; | ||||||
|  | create table file_to_post ( | ||||||
|  |     file_id bigint,  | ||||||
|  |     post_id bigint,  | ||||||
|  |  | ||||||
|  |     primary key (file_id, post_id) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | create table group_block ( | ||||||
|  |    group_id integer not null /* comment 'group profile is blocked from' */ references user_group (id), | ||||||
|  |    blocked integer not null /* comment 'profile that is blocked' */references profile (id), | ||||||
|  |    blocker integer not null /* comment 'user making the block'*/ references "user" (id), | ||||||
|  |    modified timestamp /* comment 'date of blocking'*/ , | ||||||
|  |  | ||||||
|  |    primary key (group_id, blocked) | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | create table group_alias ( | ||||||
|  |  | ||||||
|  |    alias varchar(64) /* comment 'additional nickname for the group'*/ , | ||||||
|  |    group_id integer not null /* comment 'group profile is blocked from'*/ references user_group (id), | ||||||
|  |    modified timestamp /* comment 'date alias was created'*/, | ||||||
|  |    primary key (alias) | ||||||
|  |  | ||||||
|  | ); | ||||||
|  | create index group_alias_group_id_idx on group_alias (group_id); | ||||||
|  |  | ||||||
|  | COMMIT; | ||||||
| @@ -108,7 +108,7 @@ function checkMirror($action_obj) | |||||||
| function main() | function main() | ||||||
| { | { | ||||||
|     // quick check for fancy URL auto-detection support in installer. |     // quick check for fancy URL auto-detection support in installer. | ||||||
|     if (isset($_SERVER['REDIRECT_URL']) && ((dirname($_SERVER['REQUEST_URI']) . '/check-fancy') === $_SERVER['REDIRECT_URL'])) { |     if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/","",(dirname($_SERVER['REQUEST_URI']))) . '/check-fancy') === $_SERVER['REDIRECT_URL']) { | ||||||
|         die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs."); |         die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs."); | ||||||
|     } |     } | ||||||
|     global $user, $action; |     global $user, $action; | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								install.php
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								install.php
									
									
									
									
									
								
							| @@ -77,7 +77,7 @@ function checkPrereqs() | |||||||
| 		if (!is_writable($fileFullPath)) { | 		if (!is_writable($fileFullPath)) { | ||||||
|     	     ?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p> |     	     ?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p> | ||||||
| 		       <p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p> | 		       <p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p> | ||||||
|     	     <? | 	     <?php | ||||||
| 		     $pass = false; | 		     $pass = false; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -219,9 +219,9 @@ function handlePost() | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     switch($dbtype) { |     switch($dbtype) { | ||||||
|       case 'mysql':    mysql_db_installer($host, $database, $username, $password, $sitename); |       case 'mysql':    mysql_db_installer($host, $database, $username, $password, $sitename, $fancy); | ||||||
|       break; |       break; | ||||||
|       case 'pgsql':    pgsql_db_installer($host, $database, $username, $password, $sitename); |       case 'pgsql':    pgsql_db_installer($host, $database, $username, $password, $sitename, $fancy); | ||||||
|       break; |       break; | ||||||
|       default: |       default: | ||||||
|     } |     } | ||||||
| @@ -232,7 +232,7 @@ function handlePost() | |||||||
| <?php | <?php | ||||||
| } | } | ||||||
|  |  | ||||||
| function pgsql_db_installer($host, $database, $username, $password, $sitename) { | function pgsql_db_installer($host, $database, $username, $password, $sitename, $fancy) { | ||||||
|   $connstring = "dbname=$database host=$host user=$username"; |   $connstring = "dbname=$database host=$host user=$username"; | ||||||
|  |  | ||||||
|   //No password would mean trust authentication used. |   //No password would mean trust authentication used. | ||||||
| @@ -298,7 +298,7 @@ function pgsql_db_installer($host, $database, $username, $password, $sitename) { | |||||||
|        |        | ||||||
| } | } | ||||||
|  |  | ||||||
| function mysql_db_installer($host, $database, $username, $password, $sitename) { | function mysql_db_installer($host, $database, $username, $password, $sitename, $fancy) { | ||||||
|   updateStatus("Starting installation..."); |   updateStatus("Starting installation..."); | ||||||
|   updateStatus("Checking database..."); |   updateStatus("Checking database..."); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,35 @@ | |||||||
|  * @link      http://laconi.ca/ |  * @link      http://laconi.ca/ | ||||||
|  */ |  */ | ||||||
| $(document).ready(function() { | $(document).ready(function() { | ||||||
|  |     function InitColors(i, E) { | ||||||
|  |         switch (parseInt(E.id.slice(-1))) { | ||||||
|  |             case 1: default: | ||||||
|  |                 $(E).val(rgb2hex($('body').css('background-color'))); | ||||||
|  |                 break; | ||||||
|  |             case 2: | ||||||
|  |                 $(E).val(rgb2hex($('#content').css('background-color'))); | ||||||
|  |                 break; | ||||||
|  |             case 3: | ||||||
|  |                 $(E).val(rgb2hex($('#aside_primary').css('background-color'))); | ||||||
|  |                 break; | ||||||
|  |             case 4: | ||||||
|  |                 $(E).val(rgb2hex($('html body').css('color'))); | ||||||
|  |                 break; | ||||||
|  |             case 5: | ||||||
|  |                 $(E).val(rgb2hex($('a').css('color'))); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function rgb2hex(rgb) { | ||||||
|  |         rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); | ||||||
|  |         function hex(x) { | ||||||
|  |             hexDigits = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); | ||||||
|  |             return isNaN(x) ? "00" : hexDigits[(x - x % 16) / 16] + hexDigits[x % 16]; | ||||||
|  |         } | ||||||
|  |         return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     function UpdateColors(S) { |     function UpdateColors(S) { | ||||||
|         C = $(S).val(); |         C = $(S).val(); | ||||||
|         switch (parseInt(S.id.slice(-1))) { |         switch (parseInt(S.id.slice(-1))) { | ||||||
| @@ -55,7 +84,7 @@ $(document).ready(function() { | |||||||
|  |  | ||||||
|         f = $.farbtastic('#color-picker', SynchColors); |         f = $.farbtastic('#color-picker', SynchColors); | ||||||
|         swatches = $('#settings_design_color .swatch'); |         swatches = $('#settings_design_color .swatch'); | ||||||
|  |         swatches.each(InitColors); | ||||||
|         swatches |         swatches | ||||||
|             .each(SynchColors) |             .each(SynchColors) | ||||||
|             .blur(function() { |             .blur(function() { | ||||||
|   | |||||||
| @@ -191,6 +191,7 @@ class Action extends HTMLOutputter // lawsuit | |||||||
|     function showStylesheets() |     function showStylesheets() | ||||||
|     { |     { | ||||||
|         if (Event::handle('StartShowStyles', array($this))) { |         if (Event::handle('StartShowStyles', array($this))) { | ||||||
|  |  | ||||||
|             if (Event::handle('StartShowLaconicaStyles', array($this))) { |             if (Event::handle('StartShowLaconicaStyles', array($this))) { | ||||||
|                 $this->element('link', array('rel' => 'stylesheet', |                 $this->element('link', array('rel' => 'stylesheet', | ||||||
|                                              'type' => 'text/css', |                                              'type' => 'text/css', | ||||||
| @@ -209,6 +210,7 @@ class Action extends HTMLOutputter // lawsuit | |||||||
|                                              'media' => 'print')); |                                              'media' => 'print')); | ||||||
|                 Event::handle('EndShowLaconicaStyles', array($this)); |                 Event::handle('EndShowLaconicaStyles', array($this)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (Event::handle('StartShowUAStyles', array($this))) { |             if (Event::handle('StartShowUAStyles', array($this))) { | ||||||
|                 $this->comment('[if IE]><link rel="stylesheet" type="text/css" '. |                 $this->comment('[if IE]><link rel="stylesheet" type="text/css" '. | ||||||
|                                'href="'.theme_path('css/ie.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]'); |                                'href="'.theme_path('css/ie.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]'); | ||||||
| @@ -223,6 +225,21 @@ class Action extends HTMLOutputter // lawsuit | |||||||
|                                'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" /><![endif]'); |                                'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" /><![endif]'); | ||||||
|                 Event::handle('EndShowUAStyles', array($this)); |                 Event::handle('EndShowUAStyles', array($this)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if (Event::handle('StartShowDesign', array($this))) { | ||||||
|  |  | ||||||
|  |                 $user = common_current_user(); | ||||||
|  |  | ||||||
|  |                 if (empty($user) || $user->viewdesigns) { | ||||||
|  |                     $design = $this->getDesign(); | ||||||
|  |  | ||||||
|  |                     if (!empty($design)) { | ||||||
|  |                         $design->showCSS($this); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 Event::handle('EndShowDesign', array($this)); | ||||||
|  |             } | ||||||
|             Event::handle('EndShowStyles', array($this)); |             Event::handle('EndShowStyles', array($this)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1074,4 +1091,15 @@ class Action extends HTMLOutputter // lawsuit | |||||||
|     { |     { | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * A design for this action | ||||||
|  |      * | ||||||
|  |      * @return Design a design object to use | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     function getDesign() | ||||||
|  |     { | ||||||
|  |         return Design::siteDesign(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -94,14 +94,6 @@ $config = | |||||||
|         array('name' => 'Just another Laconica microblog', |         array('name' => 'Just another Laconica microblog', | ||||||
|               'server' => $_server, |               'server' => $_server, | ||||||
|               'theme' => 'default', |               'theme' => 'default', | ||||||
|               'design' => |  | ||||||
|               array('backgroundcolor' => '#CEE1E9', |  | ||||||
|                     'contentcolor' => '#FFFFFF', |  | ||||||
|                     'sidebarcolor' => '#C8D1D5', |  | ||||||
|                     'textcolor' => '#000000', |  | ||||||
|                     'linkcolor' => '#002E6E', |  | ||||||
|                     'backgroundimage' => null, |  | ||||||
|                     'disposition' => 1), |  | ||||||
|               'path' => $_path, |               'path' => $_path, | ||||||
|               'logfile' => null, |               'logfile' => null, | ||||||
|               'logo' => null, |               'logo' => null, | ||||||
| @@ -261,6 +253,14 @@ $config = | |||||||
|         'sessions' => |         'sessions' => | ||||||
|         array('handle' => false, // whether to handle sessions ourselves |         array('handle' => false, // whether to handle sessions ourselves | ||||||
|               'debug' => false), // debugging output for sessions |               'debug' => false), // debugging output for sessions | ||||||
|  |         'design' => | ||||||
|  |         array('backgroundcolor' => null, // null -> 'use theme default' | ||||||
|  |               'contentcolor' => null, | ||||||
|  |               'sidebarcolor' => null, | ||||||
|  |               'textcolor' => null, | ||||||
|  |               'linkcolor' => null, | ||||||
|  |               'backgroundimage' => null, | ||||||
|  |               'disposition' => null), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
| $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); | $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); | ||||||
| @@ -277,6 +277,10 @@ $config['db'] = | |||||||
|         'quote_identifiers' => false, |         'quote_identifiers' => false, | ||||||
|         'type' => 'mysql' ); |         'type' => 'mysql' ); | ||||||
|  |  | ||||||
|  | // Backward compatibility | ||||||
|  |  | ||||||
|  | $config['site']['design'] =& $config['design']; | ||||||
|  |  | ||||||
| if (function_exists('date_default_timezone_set')) { | if (function_exists('date_default_timezone_set')) { | ||||||
|     /* Work internally in UTC */ |     /* Work internally in UTC */ | ||||||
|     date_default_timezone_set('UTC'); |     date_default_timezone_set('UTC'); | ||||||
|   | |||||||
| @@ -47,33 +47,10 @@ if (!defined('LACONICA')) { | |||||||
|  |  | ||||||
| class CurrentUserDesignAction extends Action | class CurrentUserDesignAction extends Action | ||||||
| { | { | ||||||
|  |  | ||||||
|     /** |  | ||||||
|       * Show the user's design stylesheet |  | ||||||
|       * |  | ||||||
|       * @return nothing |  | ||||||
|       */ |  | ||||||
|  |  | ||||||
|      function showStylesheets() |  | ||||||
|      { |  | ||||||
|          parent::showStylesheets(); |  | ||||||
|  |  | ||||||
|          $user = common_current_user(); |  | ||||||
|  |  | ||||||
|          if (empty($user) || $user->viewdesigns) { |  | ||||||
|              $design = $this->getDesign(); |  | ||||||
|  |  | ||||||
|              if (!empty($design)) { |  | ||||||
|                  $design->showCSS($this); |  | ||||||
|              } |  | ||||||
|          } |  | ||||||
|      } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * A design for this action |      * A design for this action | ||||||
|      * |      * | ||||||
|      * if the user attribute has been set, returns that user's |      * Returns the design preferences for the current user. | ||||||
|      * design. |  | ||||||
|      * |      * | ||||||
|      * @return Design a design object to use |      * @return Design a design object to use | ||||||
|      */ |      */ | ||||||
| @@ -82,11 +59,15 @@ class CurrentUserDesignAction extends Action | |||||||
|     { |     { | ||||||
|         $cur = common_current_user(); |         $cur = common_current_user(); | ||||||
|  |  | ||||||
|         if (empty($cur)) { |         if (!empty($cur)) { | ||||||
|             return null; |  | ||||||
|  |             $design = $cur->getDesign(); | ||||||
|  |  | ||||||
|  |             if (!empty($design)) { | ||||||
|  |                 return $design; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return $cur->getDesign(); |         return parent::getDesign(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -182,7 +182,7 @@ class DesignSettingsAction extends AccountSettingsAction | |||||||
|                                           'class' => 'swatch', |                                           'class' => 'swatch', | ||||||
|                                           'maxlength' => '7', |                                           'maxlength' => '7', | ||||||
|                                           'size' => '7', |                                           'size' => '7', | ||||||
|                                           'value' => '#' . $bgcolor->hexValue())); |                                           'value' => '')); | ||||||
|             $this->elementEnd('li'); |             $this->elementEnd('li'); | ||||||
|  |  | ||||||
|             $ccolor = new WebColor($design->contentcolor); |             $ccolor = new WebColor($design->contentcolor); | ||||||
| @@ -195,7 +195,7 @@ class DesignSettingsAction extends AccountSettingsAction | |||||||
|                                           'class' => 'swatch', |                                           'class' => 'swatch', | ||||||
|                                           'maxlength' => '7', |                                           'maxlength' => '7', | ||||||
|                                           'size' => '7', |                                           'size' => '7', | ||||||
|                                           'value' => '#' . $ccolor->hexValue())); |                                           'value' => '')); | ||||||
|             $this->elementEnd('li'); |             $this->elementEnd('li'); | ||||||
|  |  | ||||||
|             $sbcolor = new WebColor($design->sidebarcolor); |             $sbcolor = new WebColor($design->sidebarcolor); | ||||||
| @@ -208,7 +208,7 @@ class DesignSettingsAction extends AccountSettingsAction | |||||||
|                                         'class' => 'swatch', |                                         'class' => 'swatch', | ||||||
|                                         'maxlength' => '7', |                                         'maxlength' => '7', | ||||||
|                                         'size' => '7', |                                         'size' => '7', | ||||||
|                                         'value' => '#' . $sbcolor->hexValue())); |                                         'value' => '')); | ||||||
|             $this->elementEnd('li'); |             $this->elementEnd('li'); | ||||||
|  |  | ||||||
|             $tcolor = new WebColor($design->textcolor); |             $tcolor = new WebColor($design->textcolor); | ||||||
| @@ -221,7 +221,7 @@ class DesignSettingsAction extends AccountSettingsAction | |||||||
|                                         'class' => 'swatch', |                                         'class' => 'swatch', | ||||||
|                                         'maxlength' => '7', |                                         'maxlength' => '7', | ||||||
|                                         'size' => '7', |                                         'size' => '7', | ||||||
|                                         'value' => '#' . $tcolor->hexValue())); |                                         'value' => '')); | ||||||
|             $this->elementEnd('li'); |             $this->elementEnd('li'); | ||||||
|  |  | ||||||
|             $lcolor = new WebColor($design->linkcolor); |             $lcolor = new WebColor($design->linkcolor); | ||||||
| @@ -234,7 +234,7 @@ class DesignSettingsAction extends AccountSettingsAction | |||||||
|                                          'class' => 'swatch', |                                          'class' => 'swatch', | ||||||
|                                          'maxlength' => '7', |                                          'maxlength' => '7', | ||||||
|                                          'size' => '7', |                                          'size' => '7', | ||||||
|                                          'value' => '#' . $lcolor->hexValue())); |                                          'value' => '')); | ||||||
|             $this->elementEnd('li'); |             $this->elementEnd('li'); | ||||||
|  |  | ||||||
|         } catch (WebColorException $e) { |         } catch (WebColorException $e) { | ||||||
|   | |||||||
| @@ -49,26 +49,6 @@ class GroupDesignAction extends Action { | |||||||
|     /** The group in question */ |     /** The group in question */ | ||||||
|     var $group = null; |     var $group = null; | ||||||
|  |  | ||||||
|     /** |  | ||||||
|       * Show the groups's design stylesheet |  | ||||||
|       * |  | ||||||
|       * @return nothing |  | ||||||
|       */ |  | ||||||
|      function showStylesheets() |  | ||||||
|      { |  | ||||||
|          parent::showStylesheets(); |  | ||||||
|  |  | ||||||
|          $user = common_current_user(); |  | ||||||
|  |  | ||||||
|          if (empty($user) || $user->viewdesigns) { |  | ||||||
|              $design = $this->getDesign(); |  | ||||||
|  |  | ||||||
|              if (!empty($design)) { |  | ||||||
|                  $design->showCSS($this); |  | ||||||
|              } |  | ||||||
|          } |  | ||||||
|      } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * A design for this action |      * A design for this action | ||||||
|      * |      * | ||||||
| @@ -80,10 +60,12 @@ class GroupDesignAction extends Action { | |||||||
|  |  | ||||||
|     function getDesign() |     function getDesign() | ||||||
|     { |     { | ||||||
|         if (empty($this->group)) { |         if (!empty($this->group)) { | ||||||
|             return null; |             $design = $this->group->getDesign(); | ||||||
|  |             if (!empty($design)) { | ||||||
|  |                 return $design; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |         return parent::getDesign(); | ||||||
|         return $this->group->getDesign(); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -52,26 +52,6 @@ class OwnerDesignAction extends Action { | |||||||
|  |  | ||||||
|     var $user = null; |     var $user = null; | ||||||
|  |  | ||||||
|     /** |  | ||||||
|       * Show the owner's design stylesheet |  | ||||||
|       * |  | ||||||
|       * @return nothing |  | ||||||
|       */ |  | ||||||
|      function showStylesheets() |  | ||||||
|      { |  | ||||||
|          parent::showStylesheets(); |  | ||||||
|  |  | ||||||
|          $user = common_current_user(); |  | ||||||
|  |  | ||||||
|          if (empty($user) || $user->viewdesigns) { |  | ||||||
|              $design = $this->getDesign(); |  | ||||||
|  |  | ||||||
|              if (!empty($design)) { |  | ||||||
|                  $design->showCSS($this); |  | ||||||
|              } |  | ||||||
|          } |  | ||||||
|      } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * A design for this action |      * A design for this action | ||||||
|      * |      * | ||||||
| @@ -83,10 +63,15 @@ class OwnerDesignAction extends Action { | |||||||
|  |  | ||||||
|     function getDesign() |     function getDesign() | ||||||
|     { |     { | ||||||
|         if (empty($this->user)) { |         if (!empty($this->user)) { | ||||||
|             return null; |  | ||||||
|  |             $design = $this->user->getDesign(); | ||||||
|  |  | ||||||
|  |             if (!empty($design)) { | ||||||
|  |                 return $design; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return $this->user->getDesign(); |         return parent::getDesign(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -113,6 +113,16 @@ class Router | |||||||
|  |  | ||||||
|         $m->connect('main/tagother/:id', array('action' => 'tagother')); |         $m->connect('main/tagother/:id', array('action' => 'tagother')); | ||||||
|  |  | ||||||
|  |         $m->connect('main/oembed.xml', | ||||||
|  |                     array('action' => 'api', | ||||||
|  |                           'method' => 'oembed.xml', | ||||||
|  |                           'apiaction' => 'oembed')); | ||||||
|  |  | ||||||
|  |         $m->connect('main/oembed.json', | ||||||
|  |                     array('action' => 'api', | ||||||
|  |                           'method' => 'oembed.json', | ||||||
|  |                           'apiaction' => 'oembed')); | ||||||
|  |  | ||||||
|         // these take a code |         // these take a code | ||||||
|  |  | ||||||
|         foreach (array('register', 'confirmaddress', 'recoverpassword') as $c) { |         foreach (array('register', 'confirmaddress', 'recoverpassword') as $c) { | ||||||
| @@ -129,11 +139,6 @@ class Router | |||||||
|             $m->connect('index.php?action=' . $action, array('action' => $action)); |             $m->connect('index.php?action=' . $action, array('action' => $action)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $m->connect('main/:method', |  | ||||||
|                     array('action' => 'api', |  | ||||||
|                           'method' => 'oembed(.xml|.json)?', |  | ||||||
|                           'apiaction' => 'oembed')); |  | ||||||
|  |  | ||||||
|         // settings |         // settings | ||||||
|  |  | ||||||
|         foreach (array('profile', 'avatar', 'password', 'openid', 'im', |         foreach (array('profile', 'avatar', 'password', 'openid', 'im', | ||||||
|   | |||||||
| @@ -213,6 +213,26 @@ class TwitterapiAction extends Action | |||||||
|         return $twitter_status; |         return $twitter_status; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     function twitter_group_array($group) | ||||||
|  |     { | ||||||
|  |         $twitter_group=array(); | ||||||
|  |         $twitter_group['id']=$group->id; | ||||||
|  |         $twitter_group['url']=$group->permalink(); | ||||||
|  |         $twitter_group['nickname']=$group->nickname; | ||||||
|  |         $twitter_group['fullname']=$group->fullname; | ||||||
|  |         $twitter_group['homepage_url']=$group->homepage_url; | ||||||
|  |         $twitter_group['original_logo']=$group->original_logo; | ||||||
|  |         $twitter_group['homepage_logo']=$group->homepage_logo; | ||||||
|  |         $twitter_group['stream_logo']=$group->stream_logo; | ||||||
|  |         $twitter_group['mini_logo']=$group->mini_logo; | ||||||
|  |         $twitter_group['homepage']=$group->homepage; | ||||||
|  |         $twitter_group['description']=$group->description; | ||||||
|  |         $twitter_group['location']=$group->location; | ||||||
|  |         $twitter_group['created']=$this->date_twitter($group->created); | ||||||
|  |         $twitter_group['modified']=$this->date_twitter($group->modified); | ||||||
|  |         return $twitter_group; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     function twitter_rss_entry_array($notice) |     function twitter_rss_entry_array($notice) | ||||||
|     { |     { | ||||||
|         $profile = $notice->getProfile(); |         $profile = $notice->getProfile(); | ||||||
| @@ -413,6 +433,15 @@ class TwitterapiAction extends Action | |||||||
|         $this->elementEnd('status'); |         $this->elementEnd('status'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     function show_twitter_xml_group($twitter_group) | ||||||
|  |     { | ||||||
|  |         $this->elementStart('group'); | ||||||
|  |         foreach($twitter_group as $element => $value) { | ||||||
|  |             $this->element($element, null, $value); | ||||||
|  |         } | ||||||
|  |         $this->elementEnd('group'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     function show_twitter_xml_user($twitter_user, $role='user') |     function show_twitter_xml_user($twitter_user, $role='user') | ||||||
|     { |     { | ||||||
|         $this->elementStart($role); |         $this->elementStart($role); | ||||||
| @@ -450,12 +479,12 @@ class TwitterapiAction extends Action | |||||||
|         $this->element('link', null, $entry['link']); |         $this->element('link', null, $entry['link']); | ||||||
|  |  | ||||||
|         # RSS only supports 1 enclosure per item |         # RSS only supports 1 enclosure per item | ||||||
|         if($entry['enclosures']){ |         if(array_key_exists('enclosures', $entry) and !empty($entry['enclosures'])){ | ||||||
|             $enclosure = $entry['enclosures'][0]; |             $enclosure = $entry['enclosures'][0]; | ||||||
|             $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); |             $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if($entry['tags']){ |         if(array_key_exists('tags', $entry)){ | ||||||
|             foreach($entry['tags'] as $tag){ |             foreach($entry['tags'] as $tag){ | ||||||
|                 $this->element('category', null,$tag); |                 $this->element('category', null,$tag); | ||||||
|             } |             } | ||||||
| @@ -639,6 +668,22 @@ class TwitterapiAction extends Action | |||||||
|         $this->end_document('json'); |         $this->end_document('json'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     function show_single_json_group($group) | ||||||
|  |     { | ||||||
|  |         $this->init_document('json'); | ||||||
|  |         $twitter_group = $this->twitter_group_array($group); | ||||||
|  |         $this->show_json_objects($twitter_group); | ||||||
|  |         $this->end_document('json'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function show_single_xml_group($group) | ||||||
|  |     { | ||||||
|  |         $this->init_document('xml'); | ||||||
|  |         $twitter_group = $this->twitter_group_array($group); | ||||||
|  |         $this->show_twitter_xml_group($twitter_group); | ||||||
|  |         $this->end_document('xml'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Anyone know what date format this is? |     // Anyone know what date format this is? | ||||||
|     // Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach |     // Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach | ||||||
|     function date_twitter($dt) |     function date_twitter($dt) | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								lib/util.php
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								lib/util.php
									
									
									
									
									
								
							| @@ -140,7 +140,7 @@ function common_have_session() | |||||||
| function common_ensure_session() | function common_ensure_session() | ||||||
| { | { | ||||||
|     $c = null; |     $c = null; | ||||||
|     if (array_key_exists(session_name, $_COOKIE)) { |     if (array_key_exists(session_name(), $_COOKIE)) { | ||||||
|         $c = $_COOKIE[session_name()]; |         $c = $_COOKIE[session_name()]; | ||||||
|     } |     } | ||||||
|     if (!common_have_session()) { |     if (!common_have_session()) { | ||||||
| @@ -1410,20 +1410,21 @@ function common_client_ip() | |||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ($_SERVER['HTTP_X_FORWARDED_FOR']) { |     if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { | ||||||
|         if ($_SERVER['HTTP_CLIENT_IP']) { |         if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { | ||||||
|             $proxy = $_SERVER['HTTP_CLIENT_IP']; |             $proxy = $_SERVER['HTTP_CLIENT_IP']; | ||||||
|         } else { |         } else { | ||||||
|             $proxy = $_SERVER['REMOTE_ADDR']; |             $proxy = $_SERVER['REMOTE_ADDR']; | ||||||
|         } |         } | ||||||
|         $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; |         $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; | ||||||
|     } else { |     } else { | ||||||
|         if ($_SERVER['HTTP_CLIENT_IP']) { |         $proxy = null; | ||||||
|  |         if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { | ||||||
|             $ip = $_SERVER['HTTP_CLIENT_IP']; |             $ip = $_SERVER['HTTP_CLIENT_IP']; | ||||||
|         } else { |         } else { | ||||||
|             $ip = $_SERVER['REMOTE_ADDR']; |             $ip = $_SERVER['REMOTE_ADDR']; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return array($ip, $proxy); |     return array($proxy, $ip); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -122,9 +122,7 @@ class FBConnectPlugin extends Plugin | |||||||
|                                     FB_RequireFeatures( |                                     FB_RequireFeatures( | ||||||
|                                         ["XFBML"], |                                         ["XFBML"], | ||||||
|                                             function() { |                                             function() { | ||||||
|                                                 FB.init("%s", "../xd_receiver.html", |                                                 FB.init("%s", "../xd_receiver.html"); | ||||||
|                                                  {"doNotUseCachedConnectState":true }); |  | ||||||
|  |  | ||||||
|                                             } |                                             } | ||||||
|                                         ); } |                                         ); } | ||||||
|  |  | ||||||
| @@ -222,7 +220,7 @@ class FBConnectPlugin extends Plugin | |||||||
|                 try { |                 try { | ||||||
|  |  | ||||||
|                     $facebook = getFacebook(); |                     $facebook = getFacebook(); | ||||||
|                     $fbuid    = $facebook->api_client->users_getLoggedInUser(); |                     $fbuid    = $facebook->get_loggedin_user(); | ||||||
|  |  | ||||||
|                 } catch (Exception $e) { |                 } catch (Exception $e) { | ||||||
|                     common_log(LOG_WARNING, |                     common_log(LOG_WARNING, | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								plugins/recaptcha/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								plugins/recaptcha/LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net | ||||||
|  | AUTHORS: | ||||||
|  |   Mike Crawford | ||||||
|  |   Ben Maurer | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in | ||||||
|  | all copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | THE SOFTWARE. | ||||||
							
								
								
									
										23
									
								
								plugins/recaptcha/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								plugins/recaptcha/README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | Laconica reCAPTCHA plugin 0.2 8/3/09 | ||||||
|  | ==================================== | ||||||
|  | Adds a captcha to your registration page to reduce automated spam bots registering. | ||||||
|  |  | ||||||
|  | Use: | ||||||
|  | 1. Get an API key from http://recaptcha.net | ||||||
|  |  | ||||||
|  | 2. In config.php add: | ||||||
|  | include_once('plugins/recaptcha.php'); | ||||||
|  | $captcha = new recaptcha(publickey, privatekey, showErrors); | ||||||
|  |  | ||||||
|  | Changelog | ||||||
|  | ========= | ||||||
|  | 0.1 initial release | ||||||
|  | 0.2 Work around for webkit browsers | ||||||
|  |  | ||||||
|  | reCAPTCHA README | ||||||
|  | ================ | ||||||
|  |  | ||||||
|  | The reCAPTCHA PHP Lirary helps you use the reCAPTCHA API. Documentation | ||||||
|  | for this library can be found at | ||||||
|  |  | ||||||
|  | 	http://recaptcha.net/plugins/php | ||||||
							
								
								
									
										106
									
								
								plugins/recaptcha/recaptcha.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								plugins/recaptcha/recaptcha.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | |||||||
|  | <?php | ||||||
|  | /** | ||||||
|  |  * Laconica, the distributed open-source microblogging tool | ||||||
|  |  * | ||||||
|  |  * Plugin to show reCaptcha when a user registers  | ||||||
|  |  * | ||||||
|  |  * PHP version 5 | ||||||
|  |  * | ||||||
|  |  * LICENCE: This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU Affero General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU Affero General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Affero General Public License | ||||||
|  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  * | ||||||
|  |  * @category  Plugin | ||||||
|  |  * @package   Laconica | ||||||
|  |  * @author    Eric Helgeson <erichelgeson@gmail.com> | ||||||
|  |  * @copyright 2009 | ||||||
|  |  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 | ||||||
|  |  * @link      http://laconi.ca/ | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | if (!defined('LACONICA')) { | ||||||
|  |     exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | define('RECAPTCHA', '0.2'); | ||||||
|  |  | ||||||
|  | class recaptcha extends Plugin | ||||||
|  | { | ||||||
|  |     var $private_key; | ||||||
|  |     var $public_key; | ||||||
|  |     var $display_errors; | ||||||
|  |     var $failed; | ||||||
|  |     var $ssl; | ||||||
|  |  | ||||||
|  |     function __construct($public_key, $private_key, $display_errors=false) | ||||||
|  |     { | ||||||
|  |         parent::__construct(); | ||||||
|  |         require_once(INSTALLDIR.'/plugins/recaptcha/recaptchalib.php'); | ||||||
|  |         $this->public_key = $public_key; | ||||||
|  |         $this->private_key = $private_key;  | ||||||
|  |         $this->display_errors = $display_errors; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function checkssl(){ | ||||||
|  |         if(common_config('site', 'ssl') === 'sometimes' || common_config('site', 'ssl') === 'always') { | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function onStartShowHTML($action) | ||||||
|  |     { | ||||||
|  |         //XXX: Horrible hack to make Safari, FF2, and Chrome work with | ||||||
|  |         //reChapcha. reChapcha beaks xhtml strict | ||||||
|  |         header('Content-Type: text/html'); | ||||||
|  |  | ||||||
|  |         $action->extraHeaders(); | ||||||
|  |  | ||||||
|  |         $action->startXML('html', | ||||||
|  |             '-//W3C//DTD XHTML 1.0 Strict//EN', | ||||||
|  |             'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'); | ||||||
|  |  | ||||||
|  |         $action->raw('<style type="text/css">#recaptcha_area{float:left;}</style>'); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function onEndRegistrationFormData($action) | ||||||
|  |     { | ||||||
|  |         $action->elementStart('li'); | ||||||
|  |         $action->raw('<label for="recaptcha_area">Captcha</label>'); | ||||||
|  |         if($this->checkssl() === true){ | ||||||
|  |             $action->raw(recaptcha_get_html($this->public_key), null, true); | ||||||
|  |         } else {  | ||||||
|  |             $action->raw(recaptcha_get_html($this->public_key)); | ||||||
|  |         } | ||||||
|  |         $action->elementEnd('li'); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function onStartRegistrationTry($action) | ||||||
|  |     { | ||||||
|  |         $resp = recaptcha_check_answer ($this->private_key, | ||||||
|  |                                         $_SERVER["REMOTE_ADDR"], | ||||||
|  |                                         $action->trimmed('recaptcha_challenge_field'), | ||||||
|  |                                         $action->trimmed('recaptcha_response_field')); | ||||||
|  |  | ||||||
|  |         if (!$resp->is_valid)  | ||||||
|  |         { | ||||||
|  |             if($this->display_errors) | ||||||
|  |             {  | ||||||
|  |                 $action->showForm ("(reCAPTCHA said: " . $resp->error . ")"); | ||||||
|  |             } | ||||||
|  |             $action->showForm("Captcha does not match!"); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										277
									
								
								plugins/recaptcha/recaptchalib.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								plugins/recaptcha/recaptchalib.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,277 @@ | |||||||
|  | <?php | ||||||
|  | /* | ||||||
|  |  * This is a PHP library that handles calling reCAPTCHA. | ||||||
|  |  *    - Documentation and latest version | ||||||
|  |  *          http://recaptcha.net/plugins/php/ | ||||||
|  |  *    - Get a reCAPTCHA API Key | ||||||
|  |  *          http://recaptcha.net/api/getkey | ||||||
|  |  *    - Discussion group | ||||||
|  |  *          http://groups.google.com/group/recaptcha | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net | ||||||
|  |  * AUTHORS: | ||||||
|  |  *   Mike Crawford | ||||||
|  |  *   Ben Maurer | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The reCAPTCHA server URL's | ||||||
|  |  */ | ||||||
|  | define("RECAPTCHA_API_SERVER", "http://api.recaptcha.net"); | ||||||
|  | define("RECAPTCHA_API_SECURE_SERVER", "https://api-secure.recaptcha.net"); | ||||||
|  | define("RECAPTCHA_VERIFY_SERVER", "api-verify.recaptcha.net"); | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Encodes the given data into a query string format | ||||||
|  |  * @param $data - array of string elements to be encoded | ||||||
|  |  * @return string - encoded request | ||||||
|  |  */ | ||||||
|  | function _recaptcha_qsencode ($data) { | ||||||
|  |         $req = ""; | ||||||
|  |         foreach ( $data as $key => $value ) | ||||||
|  |                 $req .= $key . '=' . urlencode( stripslashes($value) ) . '&'; | ||||||
|  |  | ||||||
|  |         // Cut the last '&' | ||||||
|  |         $req=substr($req,0,strlen($req)-1); | ||||||
|  |         return $req; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Submits an HTTP POST to a reCAPTCHA server | ||||||
|  |  * @param string $host | ||||||
|  |  * @param string $path | ||||||
|  |  * @param array $data | ||||||
|  |  * @param int port | ||||||
|  |  * @return array response | ||||||
|  |  */ | ||||||
|  | function _recaptcha_http_post($host, $path, $data, $port = 80) { | ||||||
|  |  | ||||||
|  |         $req = _recaptcha_qsencode ($data); | ||||||
|  |  | ||||||
|  |         $http_request  = "POST $path HTTP/1.0\r\n"; | ||||||
|  |         $http_request .= "Host: $host\r\n"; | ||||||
|  |         $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; | ||||||
|  |         $http_request .= "Content-Length: " . strlen($req) . "\r\n"; | ||||||
|  |         $http_request .= "User-Agent: reCAPTCHA/PHP\r\n"; | ||||||
|  |         $http_request .= "\r\n"; | ||||||
|  |         $http_request .= $req; | ||||||
|  |  | ||||||
|  |         $response = ''; | ||||||
|  |         if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) { | ||||||
|  |                 die ('Could not open socket'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fwrite($fs, $http_request); | ||||||
|  |  | ||||||
|  |         while ( !feof($fs) ) | ||||||
|  |                 $response .= fgets($fs, 1160); // One TCP-IP packet | ||||||
|  |         fclose($fs); | ||||||
|  |         $response = explode("\r\n\r\n", $response, 2); | ||||||
|  |  | ||||||
|  |         return $response; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Gets the challenge HTML (javascript and non-javascript version). | ||||||
|  |  * This is called from the browser, and the resulting reCAPTCHA HTML widget | ||||||
|  |  * is embedded within the HTML form it was called from. | ||||||
|  |  * @param string $pubkey A public key for reCAPTCHA | ||||||
|  |  * @param string $error The error given by reCAPTCHA (optional, default is null) | ||||||
|  |  * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false) | ||||||
|  |  | ||||||
|  |  * @return string - The HTML to be embedded in the user's form. | ||||||
|  |  */ | ||||||
|  | function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false) | ||||||
|  | { | ||||||
|  | 	if ($pubkey == null || $pubkey == '') { | ||||||
|  | 		die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>"); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if ($use_ssl) { | ||||||
|  |                 $server = RECAPTCHA_API_SECURE_SERVER; | ||||||
|  |         } else { | ||||||
|  |                 $server = RECAPTCHA_API_SERVER; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $errorpart = ""; | ||||||
|  |         if ($error) { | ||||||
|  |            $errorpart = "&error=" . $error; | ||||||
|  |         } | ||||||
|  |         return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script> | ||||||
|  |  | ||||||
|  | 	<noscript> | ||||||
|  |   		<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/> | ||||||
|  |   		<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> | ||||||
|  |   		<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/> | ||||||
|  | 	</noscript>'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A ReCaptchaResponse is returned from recaptcha_check_answer() | ||||||
|  |  */ | ||||||
|  | class ReCaptchaResponse { | ||||||
|  |         var $is_valid; | ||||||
|  |         var $error; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |   * Calls an HTTP POST function to verify if the user's guess was correct | ||||||
|  |   * @param string $privkey | ||||||
|  |   * @param string $remoteip | ||||||
|  |   * @param string $challenge | ||||||
|  |   * @param string $response | ||||||
|  |   * @param array $extra_params an array of extra variables to post to the server | ||||||
|  |   * @return ReCaptchaResponse | ||||||
|  |   */ | ||||||
|  | function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array()) | ||||||
|  | { | ||||||
|  | 	if ($privkey == null || $privkey == '') { | ||||||
|  | 		die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ($remoteip == null || $remoteip == '') { | ||||||
|  | 		die ("For security reasons, you must pass the remote ip to reCAPTCHA"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  |         //discard spam submissions | ||||||
|  |         if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) { | ||||||
|  |                 $recaptcha_response = new ReCaptchaResponse(); | ||||||
|  |                 $recaptcha_response->is_valid = false; | ||||||
|  |                 $recaptcha_response->error = 'incorrect-captcha-sol'; | ||||||
|  |                 return $recaptcha_response; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/verify", | ||||||
|  |                                           array ( | ||||||
|  |                                                  'privatekey' => $privkey, | ||||||
|  |                                                  'remoteip' => $remoteip, | ||||||
|  |                                                  'challenge' => $challenge, | ||||||
|  |                                                  'response' => $response | ||||||
|  |                                                  ) + $extra_params | ||||||
|  |                                           ); | ||||||
|  |  | ||||||
|  |         $answers = explode ("\n", $response [1]); | ||||||
|  |         $recaptcha_response = new ReCaptchaResponse(); | ||||||
|  |  | ||||||
|  |         if (trim ($answers [0]) == 'true') { | ||||||
|  |                 $recaptcha_response->is_valid = true; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |                 $recaptcha_response->is_valid = false; | ||||||
|  |                 $recaptcha_response->error = $answers [1]; | ||||||
|  |         } | ||||||
|  |         return $recaptcha_response; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * gets a URL where the user can sign up for reCAPTCHA. If your application | ||||||
|  |  * has a configuration page where you enter a key, you should provide a link | ||||||
|  |  * using this function. | ||||||
|  |  * @param string $domain The domain where the page is hosted | ||||||
|  |  * @param string $appname The name of your application | ||||||
|  |  */ | ||||||
|  | function recaptcha_get_signup_url ($domain = null, $appname = null) { | ||||||
|  | 	return "http://recaptcha.net/api/getkey?" .  _recaptcha_qsencode (array ('domain' => $domain, 'app' => $appname)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function _recaptcha_aes_pad($val) { | ||||||
|  | 	$block_size = 16; | ||||||
|  | 	$numpad = $block_size - (strlen ($val) % $block_size); | ||||||
|  | 	return str_pad($val, strlen ($val) + $numpad, chr($numpad)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Mailhide related code */ | ||||||
|  |  | ||||||
|  | function _recaptcha_aes_encrypt($val,$ky) { | ||||||
|  | 	if (! function_exists ("mcrypt_encrypt")) { | ||||||
|  | 		die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed."); | ||||||
|  | 	} | ||||||
|  | 	$mode=MCRYPT_MODE_CBC;    | ||||||
|  | 	$enc=MCRYPT_RIJNDAEL_128; | ||||||
|  | 	$val=_recaptcha_aes_pad($val); | ||||||
|  | 	return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function _recaptcha_mailhide_urlbase64 ($x) { | ||||||
|  | 	return strtr(base64_encode ($x), '+/', '-_'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* gets the reCAPTCHA Mailhide url for a given email, public key and private key */ | ||||||
|  | function recaptcha_mailhide_url($pubkey, $privkey, $email) { | ||||||
|  | 	if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) { | ||||||
|  | 		die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " . | ||||||
|  | 		     "you can do so at <a href='http://mailhide.recaptcha.net/apikey'>http://mailhide.recaptcha.net/apikey</a>"); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  |  | ||||||
|  | 	$ky = pack('H*', $privkey); | ||||||
|  | 	$cryptmail = _recaptcha_aes_encrypt ($email, $ky); | ||||||
|  | 	 | ||||||
|  | 	return "http://mailhide.recaptcha.net/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * gets the parts of the email to expose to the user. | ||||||
|  |  * eg, given johndoe@example,com return ["john", "example.com"]. | ||||||
|  |  * the email is then displayed as john...@example.com | ||||||
|  |  */ | ||||||
|  | function _recaptcha_mailhide_email_parts ($email) { | ||||||
|  | 	$arr = preg_split("/@/", $email ); | ||||||
|  |  | ||||||
|  | 	if (strlen ($arr[0]) <= 4) { | ||||||
|  | 		$arr[0] = substr ($arr[0], 0, 1); | ||||||
|  | 	} else if (strlen ($arr[0]) <= 6) { | ||||||
|  | 		$arr[0] = substr ($arr[0], 0, 3); | ||||||
|  | 	} else { | ||||||
|  | 		$arr[0] = substr ($arr[0], 0, 4); | ||||||
|  | 	} | ||||||
|  | 	return $arr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Gets html to display an email address given a public an private key. | ||||||
|  |  * to get a key, go to: | ||||||
|  |  * | ||||||
|  |  * http://mailhide.recaptcha.net/apikey | ||||||
|  |  */ | ||||||
|  | function recaptcha_mailhide_html($pubkey, $privkey, $email) { | ||||||
|  | 	$emailparts = _recaptcha_mailhide_email_parts ($email); | ||||||
|  | 	$url = recaptcha_mailhide_url ($pubkey, $privkey, $email); | ||||||
|  | 	 | ||||||
|  | 	return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) . | ||||||
|  | 		"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]); | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ?> | ||||||
| @@ -317,6 +317,9 @@ class MailerDaemon | |||||||
|         } else if ($parsed->ctype_primary == 'text' |         } else if ($parsed->ctype_primary == 'text' | ||||||
|             && $parsed->ctype_secondary=='plain') { |             && $parsed->ctype_secondary=='plain') { | ||||||
|             $msg = $parsed->body; |             $msg = $parsed->body; | ||||||
|  |             if(strtolower($parsed->ctype_parameters['charset']) != "utf-8"){ | ||||||
|  |                 $msg = utf8_encode($msg); | ||||||
|  |             } | ||||||
|         }else if(!empty($parsed->body)){ |         }else if(!empty($parsed->body)){ | ||||||
|             if(common_config('attachments', 'uploads')){ |             if(common_config('attachments', 'uploads')){ | ||||||
|                 //only save attachments if uploads are enabled |                 //only save attachments if uploads are enabled | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								scripts/sessiongc.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								scripts/sessiongc.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | #!/usr/bin/env php | ||||||
|  | <?php | ||||||
|  | /* | ||||||
|  |  * Laconica - a distributed open-source microblogging tool | ||||||
|  |  * Copyright (C) 2008, 2009, Control Yourself, Inc. | ||||||
|  |  * | ||||||
|  |  * This program is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU Affero General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This program is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU Affero General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Affero General Public License | ||||||
|  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); | ||||||
|  |  | ||||||
|  | $helptext = <<<END_OF_GC_HELP | ||||||
|  | sessiongc.php | ||||||
|  |  | ||||||
|  | Delete old sessions from the server | ||||||
|  |  | ||||||
|  | END_OF_GC_HELP; | ||||||
|  |  | ||||||
|  | require_once INSTALLDIR.'/scripts/commandline.inc'; | ||||||
|  |  | ||||||
|  | $maxlifetime = ini_get('session.gc_maxlifetime'); | ||||||
|  |  | ||||||
|  | print "Deleting sessions older than $maxlifetime seconds.\n"; | ||||||
|  |  | ||||||
|  | Session::gc($maxlifetime); | ||||||
		Reference in New Issue
	
	Block a user