예제 #1
0
 function onStartShowSections($action)
 {
     $name = $action->trimmed('action');
     if ($name == 'tag') {
         $taginput = $action->trimmed('tag');
         $tag = common_canonical_tag($taginput);
         if (!empty($tag)) {
             $url = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=render', urlencode($tag));
             $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', urlencode($tag));
             $context = stream_context_create(array('http' => array('method' => "GET", 'header' => "User-Agent: " . $this->userAgent())));
             $html = @file_get_contents($url, false, $context);
             $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section'));
             if (!empty($html)) {
                 $action->element('style', null, "span.editsection { display: none }\n" . "table.toc { display: none }");
                 $action->raw($html);
                 $action->elementStart('p');
                 $action->element('a', array('href' => $editurl, 'title' => sprintf(_('Edit the article for #%s on WikiHashtags'), $tag)), _('Edit'));
                 $action->element('a', array('href' => 'http://www.gnu.org/copyleft/fdl.html', 'title' => _('Shared under the terms of the GNU Free Documentation License'), 'rel' => 'license'), 'GNU FDL');
                 $action->elementEnd('p');
             } else {
                 $action->element('a', array('href' => $editurl), sprintf(_('Start the article for #%s on WikiHashtags'), $tag));
             }
             $action->elementEnd('div');
         }
     }
     return true;
 }
예제 #2
0
 function onStartShowSections($action)
 {
     $name = $action->trimmed('action');
     if ($name == 'tag') {
         $taginput = $action->trimmed('tag');
         $tag = common_canonical_tag($taginput);
         if (!empty($tag)) {
             $url = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=render', urlencode($tag));
             $editurl = sprintf('http://hashtags.wikia.com/index.php?title=%s&action=edit', urlencode($tag));
             $request = HTTPClient::start();
             $response = $request->get($url);
             $html = $response->getBody();
             $action->elementStart('div', array('id' => 'wikihashtags', 'class' => 'section'));
             if ($response->isOk() && !empty($html)) {
                 $action->element('style', null, "span.editsection { display: none }\n" . "table.toc { display: none }");
                 $action->raw($html);
                 $action->elementStart('p');
                 $action->element('a', array('href' => $editurl, 'title' => sprintf(_m('Edit the article for #%s on WikiHashtags'), $tag)), _m('Edit'));
                 $action->element('a', array('href' => 'http://www.gnu.org/copyleft/fdl.html', 'title' => _m('Shared under the terms of the GNU Free Documentation License'), 'rel' => 'license'), _m('GNU FDL'));
                 $action->elementEnd('p');
             } else {
                 $action->element('a', array('href' => $editurl), sprintf(_m('Start the article for #%s on WikiHashtags'), $tag));
             }
             $action->elementEnd('div');
         }
     }
     return true;
 }
 /**
  * Take arguments for running
  *
  * @param array $args $_REQUEST args
  *
  * @return boolean success flag
  */
 function prepare($args)
 {
     parent::prepare($args);
     $taginput = $this->trimmed('tag');
     $this->tag = common_canonical_tag($taginput);
     $this->notices = $this->getNotices();
     return true;
 }
예제 #4
0
 protected function doStreamPreparation()
 {
     $tag = common_canonical_tag($this->trimmed('tag'));
     $this->tag = Notice_tag::getKV('tag', $tag);
     if (!$this->tag instanceof Notice_tag) {
         // TRANS: Client error when requesting a tag feed for a non-existing tag.
         $this->clientError(_('No such tag.'));
     }
 }
예제 #5
0
파일: tagrss.php 프로젝트: Br3nda/laconica
 function prepare($args)
 {
     parent::prepare($args);
     $tag = common_canonical_tag($this->trimmed('tag'));
     $this->tag = Notice_tag::staticGet('tag', $tag);
     if (!$this->tag) {
         $this->clientError(_('No such tag.'));
         return false;
     } else {
         return true;
     }
 }
예제 #6
0
 function prepare($args)
 {
     parent::prepare($args);
     $tag = common_canonical_tag($this->trimmed('tag'));
     $this->tag = Notice_tag::getKV('tag', $tag);
     if (!$this->tag) {
         // TRANS: Client error when requesting a tag feed for a non-existing tag.
         $this->clientError(_('No such tag.'));
     } else {
         $this->notices = $this->getNotices($this->limit);
         return true;
     }
 }
예제 #7
0
 function prepare($args)
 {
     parent::prepare($args);
     if (common_config('singleuser', 'enabled')) {
         $tagger_arg = User::singleUserNickname();
     } else {
         $tagger_arg = $this->arg('tagger');
     }
     $tag_arg = $this->arg('tag');
     $tagger = common_canonical_nickname($tagger_arg);
     $tag = common_canonical_tag($tag_arg);
     // Permanent redirect on non-canonical nickname
     if ($tagger_arg != $tagger || $tag_arg != $tag) {
         $args = array('tagger' => $nickname, 'tag' => $tag);
         if ($this->page != 1) {
             $args['page'] = $this->page;
         }
         common_redirect(common_local_url('showprofiletag', $args), 301);
         return false;
     }
     if (!$tagger) {
         // TRANS: Client error displayed when a tagger is expected but not provided.
         $this->clientError(_('No tagger.'), 404);
         return false;
     }
     $user = User::staticGet('nickname', $tagger);
     if (!$user) {
         // TRANS: Client error displayed trying to perform an action related to a non-existing user.
         $this->clientError(_('No such user.'), 404);
         return false;
     }
     $this->tagger = $user->getProfile();
     $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
     $current = common_current_user();
     $can_see = !empty($this->peopletag) && (!$this->peopletag->private || $this->peopletag->private && $this->peopletag->tagger === $current->id);
     if (!$can_see) {
         // TRANS: Client error displayed trying to reference a non-existing list.
         $this->clientError(_('No such list.'), 404);
         return false;
     }
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     $this->userProfile = Profile::current();
     $stream = new PeopletagNoticeStream($this->peopletag, $this->userProfile);
     $this->notice = $stream->getNotices(($this->page - 1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
     if ($this->page > 1 && $this->notice->N == 0) {
         // TRANS: Server error when page not found (404).
         $this->serverError(_('No such page.'), $code = 404);
     }
     return true;
 }
예제 #8
0
 protected function doStreamPreparation()
 {
     $tag = common_canonical_tag($this->arg('tag'));
     try {
         $this->peopletag = Profile_list::getByPK(array('tagger' => $this->target->getID(), 'tag' => $tag));
     } catch (NoResultException $e) {
         // TRANS: Client error displayed trying to reference a non-existing list.
         throw new ClientException('No such list.');
     }
     if ($this->peopletag->private && !$this->peopletag->getTagger()->sameAs($this->scoped)) {
         // TRANS: Client error displayed trying to reference a non-existing list.
         throw new AuthorizationException('You do not have permission to see this list.');
     }
 }
예제 #9
0
파일: tag.php 프로젝트: Br3nda/laconica
 function prepare($args)
 {
     parent::prepare($args);
     $taginput = $this->trimmed('tag');
     $this->tag = common_canonical_tag($taginput);
     if (!$this->tag) {
         common_redirect(common_local_url('publictagcloud'), 301);
         return false;
     }
     if ($this->tag != $taginput) {
         common_redirect(common_local_url('tag', array('tag' => $this->tag)));
     }
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     common_set_returnto($this->selfUrl());
     return true;
 }
예제 #10
0
 function prepare($args)
 {
     parent::prepare($args);
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     $tag_arg = $this->arg('tag');
     $tag = common_canonical_tag($tag_arg);
     // Permanent redirect on non-canonical nickname
     if ($tag_arg != $tag) {
         $args = array('tag' => $nickname);
         if ($this->page && $this->page != 1) {
             $args['page'] = $this->page;
         }
         common_redirect(common_local_url('peopletag', $args), 301);
     }
     $this->tag = $tag;
     return true;
 }
예제 #11
0
 function prepare($args)
 {
     parent::prepare($args);
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     if (common_config('singleuser', 'enabled')) {
         $tagger_arg = User::singleUserNickname();
     } else {
         $tagger_arg = $this->arg('tagger');
     }
     $tag_arg = $this->arg('tag');
     $tagger = common_canonical_nickname($tagger_arg);
     $tag = common_canonical_tag($tag_arg);
     // Permanent redirect on non-canonical nickname
     if ($tagger_arg != $tagger || $tag_arg != $tag) {
         $args = array('tagger' => $nickname, 'tag' => $tag);
         if ($this->page != 1) {
             $args['page'] = $this->page;
         }
         common_redirect(common_local_url('peopletagged', $args), 301);
         return false;
     }
     if (!$tagger) {
         // TRANS: Client error displayed when a tagger is expected but not provided.
         $this->clientError(_('No tagger.'), 404);
         return false;
     }
     $user = User::staticGet('nickname', $tagger);
     if (!$user) {
         // TRANS: Client error displayed trying to perform an action related to a non-existing user.
         $this->clientError(_('No such user.'), 404);
         return false;
     }
     $this->tagger = $user->getProfile();
     $this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
     if (!$this->peopletag) {
         // TRANS: Client error displayed trying to reference a non-existing list.
         $this->clientError(_('No such list.'), 404);
         return false;
     }
     return true;
 }
예제 #12
0
 protected function prepare(array $args = array())
 {
     parent::prepare($args);
     $taginput = $this->trimmed('tag');
     $this->tag = common_canonical_tag($taginput);
     if (empty($this->tag)) {
         common_redirect(common_local_url('publictagcloud'), 301);
     }
     // after common_canonical_tag we have a lowercase, no-specials tag string
     if ($this->tag !== $taginput) {
         common_redirect(common_local_url('tag', array('tag' => $this->tag)), 301);
     }
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     common_set_returnto($this->selfUrl());
     $this->notice = Notice_tag::getStream($this->tag)->getNotices(($this->page - 1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
     if ($this->page > 1 && $this->notice->N == 0) {
         // TRANS: Client error when page not found (404).
         $this->clientError(_('No such page.'), 404);
     }
     return true;
 }
예제 #13
0
파일: tag.php 프로젝트: himmelex/NTW
 function prepare($args)
 {
     parent::prepare($args);
     $taginput = $this->trimmed('tag');
     $this->tag = common_canonical_tag($taginput);
     if (!$this->tag) {
         common_redirect(common_local_url('publictagcloud'), 301);
         return false;
     }
     if ($this->tag != $taginput) {
         common_redirect(common_local_url('tag', array('tag' => $this->tag)), 301);
         return false;
     }
     $this->page = $this->arg('page') ? $this->arg('page') + 0 : 1;
     common_set_returnto($this->selfUrl());
     $this->notice = Notice_tag::getStream($this->tag, ($this->page - 1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
     if ($this->page > 1 && $this->notice->N == 0) {
         // TRANS: Server error when page not found (404)
         $this->serverError(_('您访问的网页不存在'), $code = 404);
     }
     return true;
 }
예제 #14
0
 function prepare($args)
 {
     parent::prepare($args);
     $this->q = $this->trimmed('q');
     // FIXME: very dependent on tag format
     if (preg_match('/^#([\\pL\\pN_\\-\\.]{1,64})/ue', $this->q)) {
         common_redirect(common_local_url('tag', array('tag' => common_canonical_tag(substr($this->q, 1)))), 303);
     }
     if (!empty($this->q)) {
         $profile = Profile::current();
         $stream = new SearchNoticeStream($this->q, $profile);
         $page = $this->trimmed('page');
         if (empty($page)) {
             $page = 1;
         } else {
             $page = (int) $page;
         }
         $this->notice = $stream->getNotices(($page - 1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
     }
     common_set_returnto($this->selfUrl());
     return true;
 }
예제 #15
0
 function postNote($activity)
 {
     $note = $activity->objects[0];
     // Use summary as fallback for content
     if (!empty($note->content)) {
         $sourceContent = $note->content;
     } else {
         if (!empty($note->summary)) {
             $sourceContent = $note->summary;
         } else {
             if (!empty($note->title)) {
                 $sourceContent = $note->title;
             } else {
                 // @fixme fetch from $sourceUrl?
                 // TRANS: Client error displayed when posting a notice without content through the API.
                 // TRANS: %d is the notice ID (number).
                 $this->clientError(sprintf(_('No content for notice %d.'), $note->id));
             }
         }
     }
     // Get (safe!) HTML and text versions of the content
     $rendered = common_purify($sourceContent);
     $content = common_strip_html($rendered);
     $shortened = $this->auth_user->shortenLinks($content);
     $options = array('is_local' => Notice::LOCAL_PUBLIC, 'rendered' => $rendered, 'replies' => array(), 'groups' => array(), 'tags' => array(), 'urls' => array());
     // accept remote URI (not necessarily a good idea)
     common_debug("Note ID is {$note->id}");
     if (!empty($note->id)) {
         $notice = Notice::getKV('uri', trim($note->id));
         if (!empty($notice)) {
             // TRANS: Client error displayed when using another format than AtomPub.
             // TRANS: %s is the notice URI.
             $this->clientError(sprintf(_('Notice with URI "%s" already exists.'), $note->id));
         }
         common_log(LOG_NOTICE, "Saving client-supplied notice URI '{$note->id}'");
         $options['uri'] = $note->id;
     }
     // accept remote create time (also maybe not such a good idea)
     if (!empty($activity->time)) {
         common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
         $options['created'] = common_sql_date($activity->time);
     }
     // Check for optional attributes...
     if ($activity->context instanceof ActivityContext) {
         foreach ($activity->context->attention as $uri => $type) {
             try {
                 $profile = Profile::fromUri($uri);
                 if ($profile->isGroup()) {
                     $options['groups'][] = $profile->id;
                 } else {
                     $options['replies'][] = $uri;
                 }
             } catch (UnknownUriException $e) {
                 common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri));
             }
         }
         // Maintain direct reply associations
         // @fixme what about conversation ID?
         if (!empty($activity->context->replyToID)) {
             $orig = Notice::getKV('uri', $activity->context->replyToID);
             if (!empty($orig)) {
                 $options['reply_to'] = $orig->id;
             }
         }
         $location = $activity->context->location;
         if ($location) {
             $options['lat'] = $location->lat;
             $options['lon'] = $location->lon;
             if ($location->location_id) {
                 $options['location_ns'] = $location->location_ns;
                 $options['location_id'] = $location->location_id;
             }
         }
     }
     // Atom categories <-> hashtags
     foreach ($activity->categories as $cat) {
         if ($cat->term) {
             $term = common_canonical_tag($cat->term);
             if ($term) {
                 $options['tags'][] = $term;
             }
         }
     }
     // Atom enclosures -> attachment URLs
     foreach ($activity->enclosures as $href) {
         // @fixme save these locally or....?
         $options['urls'][] = $href;
     }
     $saved = Notice::saveNew($this->target->id, $content, 'atompub', $options);
     return $saved;
 }
예제 #16
0
 /**
  * Handle a post
  *
  * Validate input and save changes. Reload the form with a success
  * or error message.
  *
  * @return void
  */
 function handlePost()
 {
     // CSRF protection
     $token = $this->trimmed('token');
     if (!$token || $token != common_session_token()) {
         // TRANS: Form validation error.
         $this->showForm(_('There was a problem with your session token. ' . 'Try again, please.'));
         return;
     }
     if (Event::handle('StartProfileSaveForm', array($this))) {
         try {
             $nickname = Nickname::normalize($this->trimmed('nickname'));
         } catch (NicknameException $e) {
             $this->showForm($e->getMessage());
             return;
         }
         $fullname = $this->trimmed('fullname');
         $homepage = $this->trimmed('homepage');
         $bio = $this->trimmed('bio');
         $location = $this->trimmed('location');
         $autosubscribe = $this->boolean('autosubscribe');
         $subscribe_policy = $this->trimmed('subscribe_policy');
         $private_stream = $this->boolean('private_stream');
         $language = $this->trimmed('language');
         $timezone = $this->trimmed('timezone');
         $tagstring = $this->trimmed('tags');
         // Some validation
         if (!User::allowed_nickname($nickname)) {
             // TRANS: Validation error in form for profile settings.
             $this->showForm(_('Not a valid nickname.'));
             return;
         } else {
             if (!is_null($homepage) && strlen($homepage) > 0 && !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
                 // TRANS: Validation error in form for profile settings.
                 $this->showForm(_('Homepage is not a valid URL.'));
                 return;
             } else {
                 if (!is_null($fullname) && mb_strlen($fullname) > 255) {
                     // TRANS: Validation error in form for profile settings.
                     $this->showForm(_('Full name is too long (maximum 255 characters).'));
                     return;
                 } else {
                     if (Profile::bioTooLong($bio)) {
                         // TRANS: Validation error in form for profile settings.
                         // TRANS: Plural form is used based on the maximum number of allowed
                         // TRANS: characters for the biography (%d).
                         $this->showForm(sprintf(_m('Bio is too long (maximum %d character).', 'Bio is too long (maximum %d characters).', Profile::maxBio()), Profile::maxBio()));
                         return;
                     } else {
                         if (!is_null($location) && mb_strlen($location) > 255) {
                             // TRANS: Validation error in form for profile settings.
                             $this->showForm(_('Location is too long (maximum 255 characters).'));
                             return;
                         } else {
                             if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
                                 // TRANS: Validation error in form for profile settings.
                                 $this->showForm(_('Timezone not selected.'));
                                 return;
                             } else {
                                 if ($this->nicknameExists($nickname)) {
                                     // TRANS: Validation error in form for profile settings.
                                     $this->showForm(_('Nickname already in use. Try another one.'));
                                     return;
                                 } else {
                                     if (!is_null($language) && strlen($language) > 50) {
                                         // TRANS: Validation error in form for profile settings.
                                         $this->showForm(_('Language is too long (maximum 50 characters).'));
                                         return;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         $tags = array();
         $tag_priv = array();
         if (is_string($tagstring) && strlen($tagstring) > 0) {
             $tags = preg_split('/[\\s,]+/', $tagstring);
             foreach ($tags as &$tag) {
                 $private = @$tag[0] === '.';
                 $tag = common_canonical_tag($tag);
                 if (!common_valid_profile_tag($tag)) {
                     // TRANS: Validation error in form for profile settings.
                     // TRANS: %s is an invalid tag.
                     $this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
                     return;
                 }
                 $tag_priv[$tag] = $private;
             }
         }
         $user = common_current_user();
         $user->query('BEGIN');
         if ($user->nickname != $nickname || $user->language != $language || $user->timezone != $timezone) {
             common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname, __FILE__);
             common_debug('Updating user language from ' . $user->language . ' to ' . $language, __FILE__);
             common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone, __FILE__);
             $original = clone $user;
             $user->nickname = $nickname;
             $user->language = $language;
             $user->timezone = $timezone;
             $result = $user->updateKeys($original);
             if ($result === false) {
                 common_log_db_error($user, 'UPDATE', __FILE__);
                 // TRANS: Server error thrown when user profile settings could not be updated.
                 $this->serverError(_('Could not update user.'));
                 return;
             } else {
                 // Re-initialize language environment if it changed
                 common_init_language();
                 // Clear the site owner, in case nickname changed
                 if ($user->hasRole(Profile_role::OWNER)) {
                     User::blow('user:site_owner');
                 }
             }
         }
         // XXX: XOR
         if ($user->autosubscribe ^ $autosubscribe || $user->private_stream ^ $private_stream || $user->subscribe_policy != $subscribe_policy) {
             $original = clone $user;
             $user->autosubscribe = $autosubscribe;
             $user->private_stream = $private_stream;
             $user->subscribe_policy = $subscribe_policy;
             $result = $user->update($original);
             if ($result === false) {
                 common_log_db_error($user, 'UPDATE', __FILE__);
                 // TRANS: Server error thrown when user profile settings could not be updated to
                 // TRANS: automatically subscribe to any subscriber.
                 $this->serverError(_('Could not update user for autosubscribe or subscribe_policy.'));
                 return;
             }
         }
         $profile = $user->getProfile();
         $orig_profile = clone $profile;
         $profile->nickname = $user->nickname;
         $profile->fullname = $fullname;
         $profile->homepage = $homepage;
         $profile->bio = $bio;
         $profile->location = $location;
         $loc = Location::fromName($location);
         if (empty($loc)) {
             $profile->lat = null;
             $profile->lon = null;
             $profile->location_id = null;
             $profile->location_ns = null;
         } else {
             $profile->lat = $loc->lat;
             $profile->lon = $loc->lon;
             $profile->location_id = $loc->location_id;
             $profile->location_ns = $loc->location_ns;
         }
         $profile->profileurl = common_profile_url($nickname);
         if (common_config('location', 'share') == 'user') {
             $exists = false;
             $prefs = User_location_prefs::staticGet('user_id', $user->id);
             if (empty($prefs)) {
                 $prefs = new User_location_prefs();
                 $prefs->user_id = $user->id;
                 $prefs->created = common_sql_now();
             } else {
                 $exists = true;
                 $orig = clone $prefs;
             }
             $prefs->share_location = $this->boolean('sharelocation');
             if ($exists) {
                 $result = $prefs->update($orig);
             } else {
                 $result = $prefs->insert();
             }
             if ($result === false) {
                 common_log_db_error($prefs, $exists ? 'UPDATE' : 'INSERT', __FILE__);
                 // TRANS: Server error thrown when user profile location preference settings could not be updated.
                 $this->serverError(_('Could not save location prefs.'));
                 return;
             }
         }
         common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
         common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
         $result = $profile->update($orig_profile);
         if ($result === false) {
             common_log_db_error($profile, 'UPDATE', __FILE__);
             // TRANS: Server error thrown when user profile settings could not be saved.
             $this->serverError(_('Could not save profile.'));
             return;
         }
         // Set the user tags
         $result = $user->setSelfTags($tags, $tag_priv);
         if (!$result) {
             // TRANS: Server error thrown when user profile settings tags could not be saved.
             $this->serverError(_('Could not save tags.'));
             return;
         }
         $user->query('COMMIT');
         Event::handle('EndProfileSaveForm', array($this));
         common_broadcast_profile($profile);
         // TRANS: Confirmation shown when user profile settings are saved.
         $this->showForm(_('Settings saved.'), true);
     }
 }
예제 #17
0
 function handle($channel)
 {
     $profile = $this->getProfile($this->other);
     $cur = $this->user->getProfile();
     if (!$profile) {
         // TRANS: Client error displayed trying to perform an action related to a non-existing profile.
         $channel->error($cur, _('No such profile.'));
         return;
     }
     if (!$cur->canTag($profile)) {
         // TRANS: Error displayed when trying to tag a user that cannot be tagged.
         $channel->error($cur, _('You cannot tag this user.'));
         return;
     }
     $privs = array();
     $tags = preg_split('/[\\s,]+/', $this->tags);
     $clean_tags = array();
     foreach ($tags as $tag) {
         $private = @$tag[0] === '.';
         $tag = $clean_tags[] = common_canonical_tag($tag);
         if (!common_valid_profile_tag($tag)) {
             // TRANS: Error displayed if a given tag is invalid.
             // TRANS: %s is the invalid tag.
             $channel->error($cur, sprintf(_('Invalid tag: "%s".'), $tag));
             return;
         }
         $privs[$tag] = $private;
     }
     try {
         foreach ($clean_tags as $tag) {
             Profile_tag::setTag($cur->id, $profile->id, $tag, null, $privs[$tag]);
         }
     } catch (Exception $e) {
         // TRANS: Error displayed if tagging a user fails.
         // TRANS: %1$s is the tagged user, %2$s is the error message (no punctuation).
         $channel->error($cur, sprintf(_('Error tagging %1$s: %2$s'), $profile->nickname, $e->getMessage()));
         return;
     }
     // TRANS: Succes message displayed if tagging a user succeeds.
     // TRANS: %1$s is the tagged user's nickname, %2$s is a list of tags.
     // TRANS: Plural is decided based on the number of tags added (not part of message).
     $channel->output($cur, sprintf(_m('%1$s was tagged %2$s', '%1$s was tagged %2$s', count($clean_tags)), $profile->nickname, implode(_(', '), $clean_tags)));
 }
예제 #18
0
 function getTargetList($user = null, $id = null)
 {
     $tagger = $this->getTargetUser($user);
     $list = null;
     if (empty($id)) {
         $id = $this->arg('id');
     }
     if ($id) {
         if (is_numeric($id)) {
             $list = Profile_list::staticGet('id', $id);
             // only if the list with the id belongs to the tagger
             if (empty($list) || $list->tagger != $tagger->id) {
                 $list = null;
             }
         }
         if (empty($list)) {
             $tag = common_canonical_tag($id);
             $list = Profile_list::getByTaggerAndTag($tagger->id, $tag);
         }
         if (!empty($list) && $list->private) {
             if ($this->auth_user->id == $list->tagger) {
                 return $list;
             }
         } else {
             return $list;
         }
     }
     return null;
 }
예제 #19
0
파일: util.php 프로젝트: himmelex/NTW
function common_tag_link($tag)
{
    $canonical = common_canonical_tag($tag);
    if (common_config('singleuser', 'enabled')) {
        // regular TagAction isn't set up in 1user mode
        $url = common_local_url('showstream', array('nickname' => common_config('singleuser', 'nickname'), 'tag' => $canonical));
    } else {
        $url = common_local_url('tag', array('tag' => $canonical));
    }
    $xs = new XMLStringer();
    $xs->elementStart('span', 'tag');
    $xs->element('a', array('href' => $url, 'rel' => 'tag'), $tag);
    $xs->elementEnd('span');
    return $xs->getString();
}
 public static function provider()
 {
     return array(array('hello', 'hello'), array('#hello people', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span> people'), array('"#hello" people', '&quot;#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>&quot; people'), array('say "#hello" people', 'say &quot;#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>&quot; people'), array('say (#hello) people', 'say (#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>) people'), array('say [#hello] people', 'say [#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>] people'), array('say {#hello} people', 'say {#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>} people'), array('say \'#hello\' people', 'say \'#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('hello'))) . '" rel="tag">hello</a></span>\' people'), array('#éclair yummy', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('éclair'))) . '" rel="tag">éclair</a></span> yummy'), array('#维基百科 zh.wikipedia!', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('维基百科'))) . '" rel="tag">维基百科</a></span> zh.wikipedia!'), array('#Россия russia', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('Россия'))) . '" rel="tag">Россия</a></span> russia'), array('#维基百科,zh.wikipedia!', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('维基百科'))) . '" rel="tag">维基百科</a></span>,zh.wikipedia!'), array('#维基百科,zh.wikipedia!', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('维基百科'))) . '" rel="tag">维基百科</a></span>,zh.wikipedia!'));
 }
 /**
  * Process an incoming post activity from this remote feed.
  * @param Activity $activity
  * @param string $method 'push' or 'salmon'
  * @return mixed saved Notice or false
  * @fixme break up this function, it's getting nasty long
  */
 public function processPost($activity, $method)
 {
     if ($this->isGroup()) {
         // A group feed will contain posts from multiple authors.
         // @fixme validate these profiles in some way!
         $oprofile = self::ensureActorProfile($activity);
         if ($oprofile->isGroup()) {
             // Groups can't post notices in StatusNet.
             common_log(LOG_WARNING, "OStatus: skipping post with group listed as author: {$oprofile->uri} in feed from {$this->uri}");
             return false;
         }
     } else {
         $actor = $activity->actor;
         if (empty($actor)) {
             // OK here! assume the default
         } else {
             if ($actor->id == $this->uri || $actor->link == $this->uri) {
                 $this->updateFromActivityObject($actor);
             } else {
                 throw new Exception("Got an actor '{$actor->title}' ({$actor->id}) on single-user feed for {$this->uri}");
             }
         }
         $oprofile = $this;
     }
     // It's not always an ActivityObject::NOTE, but... let's just say it is.
     $note = $activity->objects[0];
     // The id URI will be used as a unique identifier for for the notice,
     // protecting against duplicate saves. It isn't required to be a URL;
     // tag: URIs for instance are found in Google Buzz feeds.
     $sourceUri = $note->id;
     $dupe = Notice::staticGet('uri', $sourceUri);
     if ($dupe) {
         common_log(LOG_INFO, "OStatus: ignoring duplicate post: {$sourceUri}");
         return false;
     }
     // We'll also want to save a web link to the original notice, if provided.
     $sourceUrl = null;
     if ($note->link) {
         $sourceUrl = $note->link;
     } else {
         if ($activity->link) {
             $sourceUrl = $activity->link;
         } else {
             if (preg_match('!^https?://!', $note->id)) {
                 $sourceUrl = $note->id;
             }
         }
     }
     // Use summary as fallback for content
     if (!empty($note->content)) {
         $sourceContent = $note->content;
     } else {
         if (!empty($note->summary)) {
             $sourceContent = $note->summary;
         } else {
             if (!empty($note->title)) {
                 $sourceContent = $note->title;
             } else {
                 // @fixme fetch from $sourceUrl?
                 throw new ClientException("No content for notice {$sourceUri}");
             }
         }
     }
     // Get (safe!) HTML and text versions of the content
     $rendered = $this->purify($sourceContent);
     $content = html_entity_decode(strip_tags($rendered));
     $shortened = common_shorten_links($content);
     // If it's too long, try using the summary, and make the
     // HTML an attachment.
     $attachment = null;
     if (Notice::contentTooLong($shortened)) {
         $attachment = $this->saveHTMLFile($note->title, $rendered);
         $summary = html_entity_decode(strip_tags($note->summary));
         if (empty($summary)) {
             $summary = $content;
         }
         $shortSummary = common_shorten_links($summary);
         if (Notice::contentTooLong($shortSummary)) {
             $url = common_shorten_url($sourceUrl);
             $shortSummary = substr($shortSummary, 0, Notice::maxContent() - (mb_strlen($url) + 2));
             $content = $shortSummary . ' ' . $url;
             // We mark up the attachment link specially for the HTML output
             // so we can fold-out the full version inline.
             $attachUrl = common_local_url('attachment', array('attachment' => $attachment->id));
             $rendered = common_render_text($shortSummary) . '<a href="' . htmlspecialchars($attachUrl) . '"' . ' class="attachment more"' . ' title="' . htmlspecialchars(_m('Show more')) . '">' . '&#8230;' . '</a>';
         }
     }
     $options = array('is_local' => Notice::REMOTE_OMB, 'url' => $sourceUrl, 'uri' => $sourceUri, 'rendered' => $rendered, 'replies' => array(), 'groups' => array(), 'tags' => array(), 'urls' => array());
     // Check for optional attributes...
     if (!empty($activity->time)) {
         $options['created'] = common_sql_date($activity->time);
     }
     if ($activity->context) {
         // Any individual or group attn: targets?
         $replies = $activity->context->attention;
         $options['groups'] = $this->filterReplies($oprofile, $replies);
         $options['replies'] = $replies;
         // Maintain direct reply associations
         // @fixme what about conversation ID?
         if (!empty($activity->context->replyToID)) {
             $orig = Notice::staticGet('uri', $activity->context->replyToID);
             if (!empty($orig)) {
                 $options['reply_to'] = $orig->id;
             }
         }
         $location = $activity->context->location;
         if ($location) {
             $options['lat'] = $location->lat;
             $options['lon'] = $location->lon;
             if ($location->location_id) {
                 $options['location_ns'] = $location->location_ns;
                 $options['location_id'] = $location->location_id;
             }
         }
     }
     // Atom categories <-> hashtags
     foreach ($activity->categories as $cat) {
         if ($cat->term) {
             $term = common_canonical_tag($cat->term);
             if ($term) {
                 $options['tags'][] = $term;
             }
         }
     }
     // Atom enclosures -> attachment URLs
     foreach ($activity->enclosures as $href) {
         // @fixme save these locally or....?
         $options['urls'][] = $href;
     }
     try {
         $saved = Notice::saveNew($oprofile->profile_id, $content, 'ostatus', $options);
         if ($saved) {
             Ostatus_source::saveNew($saved, $this, $method);
             if (!empty($attachment)) {
                 File_to_post::processNew($attachment->id, $saved->id);
             }
         }
     } catch (Exception $e) {
         common_log(LOG_ERR, "OStatus save of remote message {$sourceUri} failed: " . $e->getMessage());
         throw $e;
     }
     common_log(LOG_INFO, "OStatus saved remote message {$sourceUri} as notice id {$saved->id}");
     return $saved;
 }
예제 #22
0
 /**
  * Update a list
  *
  * @return boolean success
  */
 function handlePut()
 {
     if ($this->auth_user->id != $this->list->tagger) {
         $this->clientError(_('You cannot update lists that do not belong to you.'), 401, $this->format);
     }
     $new_list = clone $this->list;
     $new_list->tag = common_canonical_tag($this->arg('name'));
     $new_list->description = common_canonical_tag($this->arg('description'));
     $new_list->private = $this->arg('mode') === 'private' ? true : false;
     $result = $new_list->update($this->list);
     if (!$result) {
         $this->clientError(_('An error occured.'), 503, $this->format);
     }
     switch ($this->format) {
         case 'xml':
             $this->showSingleXmlList($new_list);
             break;
         case 'json':
             $this->showSingleJsonList($new_list);
             break;
         default:
             $this->clientError(_('API method not found.'), 404, $this->format);
             break;
     }
 }
예제 #23
0
 protected function doPost()
 {
     $tagstring = $this->trimmed('tags');
     $token = $this->trimmed('token');
     if (Event::handle('StartSavePeopletags', array($this, $tagstring))) {
         $tags = array();
         $tag_priv = array();
         if (is_string($tagstring) && strlen($tagstring) > 0) {
             $tags = preg_split('/[\\s,]+/', $tagstring);
             foreach ($tags as &$tag) {
                 $private = @$tag[0] === '.';
                 $tag = common_canonical_tag($tag);
                 if (!common_valid_profile_tag($tag)) {
                     // TRANS: Form validation error displayed if a given tag is invalid.
                     // TRANS: %s is the invalid tag.
                     throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag));
                 }
                 $tag_priv[$tag] = $private;
             }
         }
         $result = Profile_tag::setTags($this->scoped->getID(), $this->target->getID(), $tags, $tag_priv);
         if (!$result) {
             throw new ServerException('The tags could not be saved.');
         }
         if ($this->boolean('ajax')) {
             $this->startHTML('text/xml;charset=utf-8');
             $this->elementStart('head');
             $this->element('title', null, _m('TITLE', 'Tags'));
             $this->elementEnd('head');
             $this->elementStart('body');
             if ($this->scoped->id == $this->target->id) {
                 $widget = new SelftagsWidget($this, $this->scoped, $this->target);
                 $widget->show();
             } else {
                 $widget = new PeopletagsWidget($this, $this->scoped, $this->target);
                 $widget->show();
             }
             $this->elementEnd('body');
             $this->endHTML();
         } else {
             // TRANS: Success message if lists are saved.
             $this->msg = _('Lists saved.');
             $this->showForm();
         }
         Event::handle('EndSavePeopletags', array($this, $tagstring));
     }
 }
예제 #24
0
 /**
  * Update a list
  *
  * @return boolean success
  */
 function handlePut()
 {
     if ($this->auth_user->id != $this->list->tagger) {
         // TRANS: Client error displayed when trying to update another user's list.
         $this->clientError(_('You cannot update lists that do not belong to you.'), 401);
     }
     $new_list = clone $this->list;
     $new_list->tag = common_canonical_tag($this->arg('name'));
     $new_list->description = common_canonical_tag($this->arg('description'));
     $new_list->private = $this->arg('mode') === 'private' ? true : false;
     $result = $new_list->update($this->list);
     if (!$result) {
         // TRANS: Client error displayed when an unknown error occurs updating a list.
         $this->clientError(_('An error occured.'), 503);
     }
     switch ($this->format) {
         case 'xml':
             $this->showSingleXmlList($new_list);
             break;
         case 'json':
             $this->showSingleJsonList($new_list);
             break;
         default:
             // TRANS: Client error displayed when coming across a non-supported API method.
             $this->clientError(_('API method not found.'), 404);
     }
 }
예제 #25
0
 /**
  * Process an incoming post activity from this remote feed.
  * @param Activity $activity
  * @param string $method 'push' or 'salmon'
  * @return mixed saved Notice or false
  * @todo FIXME: Break up this function, it's getting nasty long
  */
 public function processPost($activity, $method)
 {
     $notice = null;
     $oprofile = $this->checkAuthorship($activity);
     if (empty($oprofile)) {
         return null;
     }
     // It's not always an ActivityObject::NOTE, but... let's just say it is.
     $note = $activity->objects[0];
     // The id URI will be used as a unique identifier for for the notice,
     // protecting against duplicate saves. It isn't required to be a URL;
     // tag: URIs for instance are found in Google Buzz feeds.
     $sourceUri = $note->id;
     $dupe = Notice::staticGet('uri', $sourceUri);
     if ($dupe) {
         common_log(LOG_INFO, "OStatus: ignoring duplicate post: {$sourceUri}");
         return $dupe;
     }
     // We'll also want to save a web link to the original notice, if provided.
     $sourceUrl = null;
     if ($note->link) {
         $sourceUrl = $note->link;
     } else {
         if ($activity->link) {
             $sourceUrl = $activity->link;
         } else {
             if (preg_match('!^https?://!', $note->id)) {
                 $sourceUrl = $note->id;
             }
         }
     }
     // Use summary as fallback for content
     if (!empty($note->content)) {
         $sourceContent = $note->content;
     } else {
         if (!empty($note->summary)) {
             $sourceContent = $note->summary;
         } else {
             if (!empty($note->title)) {
                 $sourceContent = $note->title;
             } else {
                 // @todo FIXME: Fetch from $sourceUrl?
                 // TRANS: Client exception. %s is a source URI.
                 throw new ClientException(sprintf(_m('No content for notice %s.'), $sourceUri));
             }
         }
     }
     // Get (safe!) HTML and text versions of the content
     $rendered = $this->purify($sourceContent);
     $content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8');
     $shortened = common_shorten_links($content);
     // If it's too long, try using the summary, and make the
     // HTML an attachment.
     $attachment = null;
     if (Notice::contentTooLong($shortened)) {
         $attachment = $this->saveHTMLFile($note->title, $rendered);
         $summary = html_entity_decode(strip_tags($note->summary), ENT_QUOTES, 'UTF-8');
         if (empty($summary)) {
             $summary = $content;
         }
         $shortSummary = common_shorten_links($summary);
         if (Notice::contentTooLong($shortSummary)) {
             $url = common_shorten_url($sourceUrl);
             $shortSummary = substr($shortSummary, 0, Notice::maxContent() - (mb_strlen($url) + 2));
             $content = $shortSummary . ' ' . $url;
             // We mark up the attachment link specially for the HTML output
             // so we can fold-out the full version inline.
             // @todo FIXME i18n: This tooltip will be saved with the site's default language
             // TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
             // TRANS: this will usually be replaced with localised text from StatusNet core messages.
             $showMoreText = _m('Show more');
             $attachUrl = common_local_url('attachment', array('attachment' => $attachment->id));
             $rendered = common_render_text($shortSummary) . '<a href="' . htmlspecialchars($attachUrl) . '"' . ' class="attachment more"' . ' title="' . htmlspecialchars($showMoreText) . '">' . '&#8230;' . '</a>';
         }
     }
     $options = array('is_local' => Notice::REMOTE, 'url' => $sourceUrl, 'uri' => $sourceUri, 'rendered' => $rendered, 'replies' => array(), 'groups' => array(), 'peopletags' => array(), 'tags' => array(), 'urls' => array());
     // Check for optional attributes...
     if (!empty($activity->time)) {
         $options['created'] = common_sql_date($activity->time);
     }
     if ($activity->context) {
         // Any individual or group attn: targets?
         $replies = $activity->context->attention;
         $options['groups'] = $this->filterReplies($oprofile, $replies);
         $options['replies'] = $replies;
         // Maintain direct reply associations
         // @todo FIXME: What about conversation ID?
         if (!empty($activity->context->replyToID)) {
             $orig = Notice::staticGet('uri', $activity->context->replyToID);
             if (!empty($orig)) {
                 $options['reply_to'] = $orig->id;
             }
         }
         $location = $activity->context->location;
         if ($location) {
             $options['lat'] = $location->lat;
             $options['lon'] = $location->lon;
             if ($location->location_id) {
                 $options['location_ns'] = $location->location_ns;
                 $options['location_id'] = $location->location_id;
             }
         }
     }
     if ($this->isPeopletag()) {
         $options['peopletags'][] = $this->localPeopletag();
     }
     // Atom categories <-> hashtags
     foreach ($activity->categories as $cat) {
         if ($cat->term) {
             $term = common_canonical_tag($cat->term);
             if ($term) {
                 $options['tags'][] = $term;
             }
         }
     }
     // Atom enclosures -> attachment URLs
     foreach ($activity->enclosures as $href) {
         // @todo FIXME: Save these locally or....?
         $options['urls'][] = $href;
     }
     try {
         $saved = Notice::saveNew($oprofile->profile_id, $content, 'ostatus', $options);
         if ($saved) {
             Ostatus_source::saveNew($saved, $this, $method);
             if (!empty($attachment)) {
                 File_to_post::processNew($attachment->id, $saved->id);
             }
         }
     } catch (Exception $e) {
         common_log(LOG_ERR, "OStatus save of remote message {$sourceUri} failed: " . $e->getMessage());
         throw $e;
     }
     common_log(LOG_INFO, "OStatus saved remote message {$sourceUri} as notice id {$saved->id}");
     return $saved;
 }
예제 #26
0
 /**
  * Record this notice to the given group inboxes for delivery.
  * Overrides the regular parsing of !group markup.
  *
  * @param string $group_ids
  * @fixme might prefer URIs as identifiers, as for replies?
  *        best with generalizations on user_group to support
  *        remote groups better.
  */
 function saveKnownGroups(array $group_ids)
 {
     $groups = array();
     foreach (array_unique($group_ids) as $id) {
         $group = User_group::getKV('id', $id);
         if ($group instanceof User_group) {
             common_log(LOG_DEBUG, "Local delivery to group id {$id}, {$group->nickname}");
             $result = $this->addToGroupInbox($group);
             if (!$result) {
                 common_log_db_error($gi, 'INSERT', __FILE__);
             }
             if (common_config('group', 'addtag')) {
                 // we automatically add a tag for every group name, too
                 $tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($group->nickname), 'notice_id' => $this->id));
                 if (is_null($tag)) {
                     $this->saveTag($group->nickname);
                 }
             }
             $groups[] = clone $group;
         } else {
             common_log(LOG_ERR, "Local delivery to group id {$id} skipped, doesn't exist");
         }
     }
     return $groups;
 }
예제 #27
0
 function postNote($user, $author, $activity)
 {
     $note = $activity->objects[0];
     $sourceUri = $note->id;
     $notice = Notice::getKV('uri', $sourceUri);
     if ($notice instanceof Notice) {
         common_log(LOG_INFO, "Notice {$sourceUri} already exists.");
         if ($this->trusted) {
             $profile = $notice->getProfile();
             $uri = $profile->getUri();
             if ($uri === $author->id) {
                 common_log(LOG_INFO, sprintf('Updating notice author from %s to %s', $author->id, $user->getUri()));
                 $orig = clone $notice;
                 $notice->profile_id = $user->id;
                 $notice->update($orig);
                 return;
             } else {
                 // TRANS: Client exception thrown when trying to import a notice by another user.
                 // TRANS: %1$s is the source URI of the notice, %2$s is the URI of the author.
                 throw new ClientException(sprintf(_('Already know about notice %1$s and ' . ' it has a different author %2$s.'), $sourceUri, $uri));
             }
         } else {
             // TRANS: Client exception thrown when trying to overwrite the author information for a non-trusted user during import.
             throw new ClientException(_('Not overwriting author info for non-trusted user.'));
         }
     }
     // Use summary as fallback for content
     if (!empty($note->content)) {
         $sourceContent = $note->content;
     } else {
         if (!empty($note->summary)) {
             $sourceContent = $note->summary;
         } else {
             if (!empty($note->title)) {
                 $sourceContent = $note->title;
             } else {
                 // @fixme fetch from $sourceUrl?
                 // TRANS: Client exception thrown when trying to import a notice without content.
                 // TRANS: %s is the notice URI.
                 throw new ClientException(sprintf(_('No content for notice %s.'), $sourceUri));
             }
         }
     }
     // Get (safe!) HTML and text versions of the content
     $rendered = common_purify($sourceContent);
     $content = common_strip_html($rendered);
     $shortened = $user->shortenLinks($content);
     $options = array('is_local' => Notice::LOCAL_PUBLIC, 'uri' => $sourceUri, 'rendered' => $rendered, 'replies' => array(), 'groups' => array(), 'tags' => array(), 'urls' => array(), 'distribute' => false);
     // Check for optional attributes...
     if (!empty($activity->time)) {
         $options['created'] = common_sql_date($activity->time);
     }
     if ($activity->context) {
         // Any individual or group attn: targets?
         list($options['groups'], $options['replies']) = $this->filterAttention($activity->context->attention);
         // Maintain direct reply associations
         // @fixme what about conversation ID?
         if (!empty($activity->context->replyToID)) {
             $orig = Notice::getKV('uri', $activity->context->replyToID);
             if ($orig instanceof Notice) {
                 $options['reply_to'] = $orig->id;
             }
         }
         $location = $activity->context->location;
         if ($location) {
             $options['lat'] = $location->lat;
             $options['lon'] = $location->lon;
             if ($location->location_id) {
                 $options['location_ns'] = $location->location_ns;
                 $options['location_id'] = $location->location_id;
             }
         }
     }
     // Atom categories <-> hashtags
     foreach ($activity->categories as $cat) {
         if ($cat->term) {
             $term = common_canonical_tag($cat->term);
             if ($term) {
                 $options['tags'][] = $term;
             }
         }
     }
     // Atom enclosures -> attachment URLs
     foreach ($activity->enclosures as $href) {
         // @fixme save these locally or....?
         $options['urls'][] = $href;
     }
     common_log(LOG_INFO, "Saving notice {$options['uri']}");
     $saved = Notice::saveNew($user->id, $content, 'restore', $options);
     return $saved;
 }
예제 #28
0
 function trySave()
 {
     $tag = common_canonical_tag($this->trimmed('tag'));
     $description = $this->trimmed('description');
     $private = $this->boolean('private');
     $delete = $this->arg('delete');
     $confirm = $this->arg('confirm');
     $cancel = $this->arg('cancel');
     if ($delete && $cancel) {
         // TRANS: Form validation error displayed if the form data for deleting a tag was incorrect.
         $this->showForm(_('Delete aborted.'));
         return;
     }
     $set_private = $private && $this->peopletag->private != $private;
     if ($delete && !$confirm) {
         // TRANS: Text in confirmation dialog for deleting a tag.
         $this->showConfirm(_('Deleting this tag will permanantly remove ' . 'all its subscription and membership records. ' . 'Do you still want to continue?'), array('delete' => 1));
         return;
     } else {
         if (common_valid_tag($tag)) {
             // TRANS: Form validation error displayed if a given tag is invalid.
             $this->showForm(_('Invalid tag.'));
             return;
         } else {
             if ($tag != $this->peopletag->tag && $this->tagExists($tag)) {
                 // TRANS: Form validation error displayed if a given tag is already present.
                 // TRANS: %s is the already present tag.
                 $this->showForm(sprintf(_('You already have a tag named %s.'), $tag));
                 return;
             } else {
                 if (Profile_list::descriptionTooLong($description)) {
                     $this->showForm(sprintf(_m('Description is too long (maximum %d character).', 'Description is too long (maximum %d characters).', Profile_list::maxDescription()), Profile_list::maxDescription()));
                     return;
                 } else {
                     if ($set_private && !$confirm && !$cancel) {
                         $fwd = array('tag' => $tag, 'description' => $description, 'private' => (int) $private);
                         // TRANS: Text in confirmation dialog for setting a tag from public to private.
                         $this->showConfirm(_('Setting a public tag as private will ' . 'permanently remove all the existing ' . 'subscriptions to it. Do you still want to continue?'), $fwd);
                         return;
                     }
                 }
             }
         }
     }
     $this->peopletag->query('BEGIN');
     $orig = clone $this->peopletag;
     $this->peopletag->tag = $tag;
     $this->peopletag->description = $description;
     if (!$set_private || $confirm) {
         $this->peopletag->private = $private;
     }
     $result = $this->peopletag->update($orig);
     if (!$result) {
         common_log_db_error($this->group, 'UPDATE', __FILE__);
         // TRANS: Server error displayed when updating a list fails.
         $this->serverError(_('Could not update list.'));
     }
     $this->peopletag->query('COMMIT');
     if ($set_private && $confirm) {
         Profile_tag_subscription::cleanup($this->peopletag);
     }
     if ($delete) {
         // This might take quite a bit of time.
         $this->peopletag->delete();
         // send home.
         common_redirect(common_local_url('all', array('nickname' => $this->tagger->nickname)), 303);
     }
     if ($tag != $orig->tag) {
         common_redirect(common_local_url('editpeopletag', array('tagger' => $this->tagger->nickname, 'tag' => $tag)), 303);
     } else {
         // TRANS: Edit list form success message.
         $this->showForm(_('Options saved.'));
     }
 }
예제 #29
0
 /**
  * Save a new notice bookmark
  *
  * @param Profile $profile     To save the bookmark for
  * @param string  $title       Title of the bookmark
  * @param string  $url         URL of the bookmark
  * @param mixed   $rawtags     array of tags or string
  * @param string  $description Description of the bookmark
  * @param array   $options     Options for the Notice::saveNew()
  *
  * @return Notice saved notice
  */
 static function saveNew($profile, $title, $url, $rawtags, $description, $options = null)
 {
     if (!common_valid_http_url($url)) {
         throw new ClientException(_m('Only web bookmarks can be posted (HTTP or HTTPS).'));
     }
     $nb = self::getByURL($profile, $url);
     if (!empty($nb)) {
         // TRANS: Client exception thrown when trying to save a new bookmark that already exists.
         throw new ClientException(_m('Bookmark already exists.'));
     }
     if (empty($options)) {
         $options = array();
     }
     if (array_key_exists('uri', $options)) {
         $other = Bookmark::getKV('uri', $options['uri']);
         if (!empty($other)) {
             // TRANS: Client exception thrown when trying to save a new bookmark that already exists.
             throw new ClientException(_m('Bookmark already exists.'));
         }
     }
     if (is_string($rawtags)) {
         if (empty($rawtags)) {
             $rawtags = array();
         } else {
             $rawtags = preg_split('/[\\s,]+/', $rawtags);
         }
     }
     $nb = new Bookmark();
     $nb->id = UUID::gen();
     $nb->profile_id = $profile->id;
     $nb->url = $url;
     $nb->title = $title;
     $nb->description = $description;
     if (array_key_exists('created', $options)) {
         $nb->created = $options['created'];
     } else {
         $nb->created = common_sql_now();
     }
     if (array_key_exists('uri', $options)) {
         $nb->uri = $options['uri'];
     } else {
         // FIXME: hacks to work around router bugs in
         // queue daemons
         $r = Router::get();
         $path = $r->build('showbookmark', array('id' => $nb->id));
         if (empty($path)) {
             $nb->uri = common_path('bookmark/' . $nb->id, false, false);
         } else {
             $nb->uri = common_local_url('showbookmark', array('id' => $nb->id), null, null, false);
         }
     }
     $nb->insert();
     $tags = array();
     $replies = array();
     // filter "for:nickname" tags
     foreach ($rawtags as $tag) {
         if (strtolower(mb_substr($tag, 0, 4)) == 'for:') {
             // skip if done by caller
             if (!array_key_exists('replies', $options)) {
                 $nickname = mb_substr($tag, 4);
                 $other = common_relative_profile($profile, $nickname);
                 if (!empty($other)) {
                     $replies[] = $other->getUri();
                 }
             }
         } else {
             $tags[] = common_canonical_tag($tag);
         }
     }
     $hashtags = array();
     $taglinks = array();
     foreach ($tags as $tag) {
         $hashtags[] = '#' . $tag;
         $attrs = array('href' => Notice_tag::url($tag), 'rel' => $tag, 'class' => 'tag');
         $taglinks[] = XMLStringer::estring('a', $attrs, $tag);
     }
     // Use user's preferences for short URLs, if possible
     try {
         $user = User::getKV('id', $profile->id);
         $shortUrl = File_redirection::makeShort($url, empty($user) ? null : $user);
     } catch (Exception $e) {
         // Don't let this stop us.
         $shortUrl = $url;
     }
     // TRANS: Bookmark content.
     // TRANS: %1$s is a title, %2$s is a short URL, %3$s is the bookmark description,
     // TRANS: %4$s is space separated list of hash tags.
     $content = sprintf(_m('"%1$s" %2$s %3$s %4$s'), $title, $shortUrl, $description, implode(' ', $hashtags));
     // TRANS: Rendered bookmark content.
     // TRANS: %1$s is a URL, %2$s the bookmark title, %3$s is the bookmark description,
     // TRANS: %4$s is space separated list of hash tags.
     $rendered = sprintf(_m('<span class="xfolkentry">' . '<a class="taggedlink" href="%1$s">%2$s</a> ' . '<span class="description">%3$s</span> ' . '<span class="meta">%4$s</span>' . '</span>'), htmlspecialchars($url), htmlspecialchars($title), htmlspecialchars($description), implode(' ', $taglinks));
     $options = array_merge(array('urls' => array($url), 'rendered' => $rendered, 'tags' => $tags, 'replies' => $replies, 'object_type' => ActivityObject::BOOKMARK), $options);
     if (!array_key_exists('uri', $options)) {
         $options['uri'] = $nb->uri;
     }
     try {
         $saved = Notice::saveNew($profile->id, $content, array_key_exists('source', $options) ? $options['source'] : 'web', $options);
     } catch (Exception $e) {
         $nb->delete();
         throw $e;
     }
     if (empty($saved)) {
         $nb->delete();
     }
     return $saved;
 }
 public static function provider()
 {
     return array(array('not a link :: no way', 'not a link :: no way'), array('link http://www.somesite.com/xyz/35637563@N00/52803365/ link', 'link <a href="http://www.somesite.com/xyz/35637563@N00/52803365/" title="http://www.somesite.com/xyz/35637563@N00/52803365/" rel="external">http://www.somesite.com/xyz/35637563@N00/52803365/</a> link'), array('http://127.0.0.1', '<a href="http://127.0.0.1/" title="http://127.0.0.1/" rel="external">http://127.0.0.1</a>'), array('127.0.0.1', '<a href="http://127.0.0.1/" title="http://127.0.0.1/" rel="external">127.0.0.1</a>'), array('127.0.0.1:99', '<a href="http://127.0.0.1:99/" title="http://127.0.0.1:99/" rel="external">127.0.0.1:99</a>'), array('127.0.0.1/Name:test.php', '<a href="http://127.0.0.1/Name:test.php" title="http://127.0.0.1/Name:test.php" rel="external">127.0.0.1/Name:test.php</a>'), array('127.0.0.1/~test', '<a href="http://127.0.0.1/~test" title="http://127.0.0.1/~test" rel="external">127.0.0.1/~test</a>'), array('127.0.0.1/+test', '<a href="http://127.0.0.1/+test" title="http://127.0.0.1/+test" rel="external">127.0.0.1/+test</a>'), array('127.0.0.1/$test', '<a href="http://127.0.0.1/$test" title="http://127.0.0.1/$test" rel="external">127.0.0.1/$test</a>'), array('127.0.0.1/\'test', '<a href="http://127.0.0.1/\'test" title="http://127.0.0.1/\'test" rel="external">127.0.0.1/\'test</a>'), array('127.0.0.1/"test', '<a href="http://127.0.0.1/" title="http://127.0.0.1/" rel="external">127.0.0.1/</a>&quot;test'), array('127.0.0.1/test"test', '<a href="http://127.0.0.1/test" title="http://127.0.0.1/test" rel="external">127.0.0.1/test</a>&quot;test'), array('127.0.0.1/-test', '<a href="http://127.0.0.1/-test" title="http://127.0.0.1/-test" rel="external">127.0.0.1/-test</a>'), array('127.0.0.1/_test', '<a href="http://127.0.0.1/_test" title="http://127.0.0.1/_test" rel="external">127.0.0.1/_test</a>'), array('127.0.0.1/!test', '<a href="http://127.0.0.1/!test" title="http://127.0.0.1/!test" rel="external">127.0.0.1/!test</a>'), array('127.0.0.1/*test', '<a href="http://127.0.0.1/*test" title="http://127.0.0.1/*test" rel="external">127.0.0.1/*test</a>'), array('127.0.0.1/test%20stuff', '<a href="http://127.0.0.1/test%20stuff" title="http://127.0.0.1/test%20stuff" rel="external">127.0.0.1/test%20stuff</a>'), array('http://[::1]:99/test.php', '<a href="http://[::1]:99/test.php" title="http://[::1]:99/test.php" rel="external">http://[::1]:99/test.php</a>'), array('http://::1/test.php', '<a href="http://::1/test.php" title="http://::1/test.php" rel="external">http://::1/test.php</a>'), array('http://::1', '<a href="http://::1/" title="http://::1/" rel="external">http://::1</a>'), array('2001:4978:1b5:0:21d:e0ff:fe66:59ab/test.php', '<a href="http://*****:*****@example.com', '<a href="mailto:user@example.com" title="mailto:user@example.com" rel="external">user@example.com</a>'), array('*****@*****.**', '<a href="mailto:user_name+other@example.com" title="mailto:user_name+other@example.com" rel="external">user_name+other@example.com</a>'), array('mailto:user@example.com', '<a href="mailto:user@example.com" title="mailto:user@example.com" rel="external">mailto:user@example.com</a>'), array('mailto:user@example.com?subject=test', '<a href="mailto:user@example.com?subject=test" title="mailto:user@example.com?subject=test" rel="external">mailto:user@example.com?subject=test</a>'), array('xmpp:user@example.com', '<a href="xmpp:user@example.com" title="xmpp:user@example.com" rel="external">xmpp:user@example.com</a>'), array('#example', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('example'))) . '" rel="tag">example</a></span>'), array('#example.com', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('example.com'))) . '" rel="tag">example.com</a></span>'), array('#.net', '#<span class="tag"><a href="' . common_local_url('tag', array('tag' => common_canonical_tag('.net'))) . '" rel="tag">.net</a></span>'), array('http://example', '<a href="http://example/" title="http://example/" rel="external">http://example</a>'), array('http://3xampl3', '<a href="http://3xampl3/" title="http://3xampl3/" rel="external">http://3xampl3</a>'), array('http://example/', '<a href="http://example/" title="http://example/" rel="external">http://example/</a>'), array('http://example/path', '<a href="http://example/path" title="http://example/path" rel="external">http://example/path</a>'), array('http://example.com', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>'), array('https://example.com', '<a href="https://example.com/" title="https://example.com/" rel="external">https://example.com</a>'), array('ftp://example.com', '<a href="ftp://example.com/" title="ftp://example.com/" rel="external">ftp://example.com</a>'), array('ftps://example.com', '<a href="ftps://example.com/" title="ftps://example.com/" rel="external">ftps://example.com</a>'), array('http://user@example.com', '<a href="http://user@example.com/" title="http://user@example.com/" rel="external">http://user@example.com</a>'), array('http://*****:*****@example.com', '<a href="http://*****:*****@example.com/" title="http://*****:*****@example.com/" rel="external">http://user:pass@example.com</a>'), array('http://example.com:8080', '<a href="http://example.com:8080/" title="http://example.com:8080/" rel="external">http://example.com:8080</a>'), array('http://example.com:8080/test.php', '<a href="http://example.com:8080/test.php" title="http://example.com:8080/test.php" rel="external">http://example.com:8080/test.php</a>'), array('example.com:8080/test.php', '<a href="http://example.com:8080/test.php" title="http://example.com:8080/test.php" rel="external">example.com:8080/test.php</a>'), array('http://www.example.com', '<a href="http://www.example.com/" title="http://www.example.com/" rel="external">http://www.example.com</a>'), array('http://example.com/', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com/</a>'), array('http://example.com/path', '<a href="http://example.com/path" title="http://example.com/path" rel="external">http://example.com/path</a>'), array('http://example.com/path.html', '<a href="http://example.com/path.html" title="http://example.com/path.html" rel="external">http://example.com/path.html</a>'), array('http://example.com/path.html#fragment', '<a href="http://example.com/path.html#fragment" title="http://example.com/path.html#fragment" rel="external">http://example.com/path.html#fragment</a>'), array('http://example.com/path.php?foo=bar&bar=foo', '<a href="http://example.com/path.php?foo=bar&amp;bar=foo" title="http://example.com/path.php?foo=bar&amp;bar=foo" rel="external">http://example.com/path.php?foo=bar&amp;bar=foo</a>'), array('http://example.com.', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>.'), array('http://müllärör.de', '<a href="http://m&#xFC;ll&#xE4;r&#xF6;r.de/" title="http://m&#xFC;ll&#xE4;r&#xF6;r.de/" rel="external">http://müllärör.de</a>'), array('http://ﺱﺲﺷ.com', '<a href="http://&#xFEB1;&#xFEB2;&#xFEB7;.com/" title="http://&#xFEB1;&#xFEB2;&#xFEB7;.com/" rel="external">http://ﺱﺲﺷ.com</a>'), array('http://сделаткартинки.com', '<a href="http://&#x441;&#x434;&#x435;&#x43B;&#x430;&#x442;&#x43A;&#x430;&#x440;&#x442;&#x438;&#x43D;&#x43A;&#x438;.com/" title="http://&#x441;&#x434;&#x435;&#x43B;&#x430;&#x442;&#x43A;&#x430;&#x440;&#x442;&#x438;&#x43D;&#x43A;&#x438;.com/" rel="external">http://сделаткартинки.com</a>'), array('http://tūdaliņ.lv', '<a href="http://t&#x16B;dali&#x146;.lv/" title="http://t&#x16B;dali&#x146;.lv/" rel="external">http://tūdaliņ.lv</a>'), array('http://brændendekærlighed.com', '<a href="http://br&#xE6;ndendek&#xE6;rlighed.com/" title="http://br&#xE6;ndendek&#xE6;rlighed.com/" rel="external">http://brændendekærlighed.com</a>'), array('http://あーるいん.com', '<a href="http://&#x3042;&#x30FC;&#x308B;&#x3044;&#x3093;.com/" title="http://&#x3042;&#x30FC;&#x308B;&#x3044;&#x3093;.com/" rel="external">http://あーるいん.com</a>'), array('http://예비교사.com', '<a href="http://&#xC608;&#xBE44;&#xAD50;&#xC0AC;.com/" title="http://&#xC608;&#xBE44;&#xAD50;&#xC0AC;.com/" rel="external">http://예비교사.com</a>'), array('http://example.com.', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>.'), array('http://example.com?', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>?'), array('http://example.com!', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>!'), array('http://example.com,', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>,'), array('http://example.com;', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>;'), array('http://example.com:', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>:'), array('\'http://example.com\'', '\'<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>\''), array('"http://example.com"', '&quot;<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>&quot;'), array('"http://example.com/"', '&quot;<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com/</a>&quot;'), array('http://example.com', '<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>'), array('(http://example.com)', '(<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>)'), array('[http://example.com]', '[<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>]'), array('<http://example.com>', '&lt;<a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a>&gt;'), array('http://example.com/path/(foo)/bar', '<a href="http://example.com/path/(foo)/bar" title="http://example.com/path/(foo)/bar" rel="external">http://example.com/path/(foo)/bar</a>'), array('http://example.com/path/[foo]/bar', '<a href="http://example.com/path/" title="http://example.com/path/" rel="external">http://example.com/path/</a>[foo]/bar'), array('http://example.com/path/foo/(bar)', '<a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">http://example.com/path/foo/(bar)</a>'), array('http://example.com/path/foo/[bar]', '<a href="http://example.com/path/foo/" title="http://example.com/path/foo/" rel="external">http://example.com/path/foo/</a>[bar]'), array('Hey, check out my cool site http://example.com okay?', 'Hey, check out my cool site <a href="http://example.com/" title="http://example.com/" rel="external">http://example.com</a> okay?'), array('What about parens (e.g. http://example.com/path/foo/(bar))?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">http://example.com/path/foo/(bar)</a>)?'), array('What about parens (e.g. http://example.com/path/foo/(bar)?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">http://example.com/path/foo/(bar)</a>?'), array('What about parens (e.g. http://example.com/path/foo/(bar).)?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">http://example.com/path/foo/(bar)</a>.)?'), array('What about parens (e.g. http://example.com/path/(foo,bar)?', 'What about parens (e.g. <a href="http://example.com/path/(foo,bar)" title="http://example.com/path/(foo,bar)" rel="external">http://example.com/path/(foo,bar)</a>?'), array('Unbalanced too (e.g. http://example.com/path/((((foo)/bar)?', 'Unbalanced too (e.g. <a href="http://example.com/path/((((foo)/bar)" title="http://example.com/path/((((foo)/bar)" rel="external">http://example.com/path/((((foo)/bar)</a>?'), array('Unbalanced too (e.g. http://example.com/path/(foo))))/bar)?', 'Unbalanced too (e.g. <a href="http://example.com/path/(foo))))/bar" title="http://example.com/path/(foo))))/bar" rel="external">http://example.com/path/(foo))))/bar</a>)?'), array('Unbalanced too (e.g. http://example.com/path/foo/((((bar)?', 'Unbalanced too (e.g. <a href="http://example.com/path/foo/((((bar)" title="http://example.com/path/foo/((((bar)" rel="external">http://example.com/path/foo/((((bar)</a>?'), array('Unbalanced too (e.g. http://example.com/path/foo/(bar))))?', 'Unbalanced too (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">http://example.com/path/foo/(bar)</a>)))?'), array('example.com', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>'), array('example.org', '<a href="http://example.org/" title="http://example.org/" rel="external">example.org</a>'), array('example.co.uk', '<a href="http://example.co.uk/" title="http://example.co.uk/" rel="external">example.co.uk</a>'), array('www.example.co.uk', '<a href="http://www.example.co.uk/" title="http://www.example.co.uk/" rel="external">www.example.co.uk</a>'), array('farm1.images.example.co.uk', '<a href="http://farm1.images.example.co.uk/" title="http://farm1.images.example.co.uk/" rel="external">farm1.images.example.co.uk</a>'), array('example.museum', '<a href="http://example.museum/" title="http://example.museum/" rel="external">example.museum</a>'), array('example.travel', '<a href="http://example.travel/" title="http://example.travel/" rel="external">example.travel</a>'), array('example.com.', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>.'), array('example.com?', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>?'), array('example.com!', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>!'), array('example.com,', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>,'), array('example.com;', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>;'), array('example.com:', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>:'), array('\'example.com\'', '\'<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>\''), array('"example.com"', '&quot;<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>&quot;'), array('example.com', '<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>'), array('(example.com)', '(<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>)'), array('[example.com]', '[<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>]'), array('<example.com>', '&lt;<a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>&gt;'), array('Hey, check out my cool site example.com okay?', 'Hey, check out my cool site <a href="http://example.com/" title="http://example.com/" rel="external">example.com</a> okay?'), array('Hey, check out my cool site example.com.I made it.', 'Hey, check out my cool site <a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>.I made it.'), array('Hey, check out my cool site example.com.Funny thing...', 'Hey, check out my cool site <a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>.Funny thing...'), array('Hey, check out my cool site example.com.You will love it.', 'Hey, check out my cool site <a href="http://example.com/" title="http://example.com/" rel="external">example.com</a>.You will love it.'), array('What about parens (e.g. example.com/path/foo/(bar))?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">example.com/path/foo/(bar)</a>)?'), array('What about parens (e.g. example.com/path/foo/(bar)?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">example.com/path/foo/(bar)</a>?'), array('What about parens (e.g. example.com/path/foo/(bar).)?', 'What about parens (e.g. <a href="http://example.com/path/foo/(bar)" title="http://example.com/path/foo/(bar)" rel="external">example.com/path/foo/(bar)</a>.)?'), array('What about parens (e.g. example.com/path/(foo,bar)?', 'What about parens (e.g. <a href="http://example.com/path/(foo,bar)" title="http://example.com/path/(foo,bar)" rel="external">example.com/path/(foo,bar)</a>?'), array('file.ext', 'file.ext'), array('file.html', 'file.html'), array('file.php', 'file.php'));
 }