(if you're using apache), check that the LimitRequestBody directive isn't
set too low (it's optional, so it may not be there at all).
+process_links: follow redirects and save all available file information
+ (mimetype, date, size, oembed, etc.). Defaults to true.
file_quota: maximum size for a single file upload in bytes. A user can send
any amount of notices with attachments as long as each attachment
is smaller than file_quota.
It is shared with you in hope that you too make an
service available to your users. To learn more,
please see the Open Software Service Definition
-1.1:
-
- http://www.opendefinition.org/ossd
+1.1: <http://www.opendefinition.org/ossd>
### License
Documentation in the /doc-src/ directory is available under the
Creative Commons Attribution 3.0 Unported license, with attribution to
-"GNU social". See http://creativecommons.org/licenses/by/3.0/ for details.
+"GNU social". See <http://creativecommons.org/licenses/by/3.0/> for details.
CSS and images in the /theme/ directory are available under the
Creative Commons Attribution 3.0 Unported license, with attribution to
-"GNU social". See http://creativecommons.org/licenses/by/3.0/ for details.
+"GNU social". See <http://creativecommons.org/licenses/by/3.0/> for details.
Our understanding and intention is that if you add your own theme that
uses only CSS and images, those files are not subject to the copyleft
requirements of the Affero General Public License 3.0. See
-http://wordpress.org/news/2009/07/themes-are-gpl-too/ . This is not
+<http://wordpress.org/news/2009/07/themes-are-gpl-too/>. This is not
legal advice; consult your lawyer.
Additional library software has been made available in the 'extlib'
So far it includes the following changes:
-- XSS security fix (thanks Simon Waters, https://www.surevine.com/ )
+- XSS security fix (thanks Simon Waters, <https://www.surevine.com/> )
Upgrades from _StatusNet_ 1.1.1 will also experience these improvements:
There are several ways to get more information about GNU social.
* The #social IRC channel on freenode.net <http://www.freenode.net/>.
-* The GNU social website
-* Following us on GNU social -- http://quitter.se/gnusocial
+* The GNU social website <http://gnu.io/social/>
+* Following us on GNU social -- <http://quitter.se/gnusocial>
* GNU social has a bug tracker for any defects you may find, or ideas for
- making things better. http://bugz.foocorp.net/
+ making things better. <http://bugz.foocorp.net/>
* Patches are welcome, either on the bug tracker or our repository at
- Gitorious. https://gitorious.org/social/mainline
+ Gitorious. <https://gitorious.org/social/mainline>
Credits
=======
return array(new Feed(Feed::JSON,
common_local_url('ApiTimelineNetworkPublic',
array('format' => 'as')),
- // TRANS: Link description for public timeline feed.
- _('Public Timeline Feed (Activity Streams JSON)')),
+ // TRANS: Link description for the _global_ network public timeline feed.
+ _('Network Public Timeline Feed (Activity Streams JSON)')),
new Feed(Feed::RSS1, common_local_url('publicrss'),
- // TRANS: Link description for public timeline feed.
- _('Public Timeline Feed (RSS 1.0)')),
+ // TRANS: Link description for the _global_ network public timeline feed.
+ _('Network Public Timeline Feed (RSS 1.0)')),
new Feed(Feed::RSS2,
common_local_url('ApiTimelineNetworkPublic',
array('format' => 'rss')),
- // TRANS: Link description for public timeline feed.
- _('Public Timeline Feed (RSS 2.0)')),
+ // TRANS: Link description for the _global_ network public timeline feed.
+ _('Network Public Timeline Feed (RSS 2.0)')),
new Feed(Feed::ATOM,
common_local_url('ApiTimelineNetworkPublic',
array('format' => 'atom')),
- // TRANS: Link description for public timeline feed.
- _('Public Timeline Feed (Atom)')));
+ // TRANS: Link description for the _global_ network public timeline feed.
+ _('Network Public Timeline Feed (Atom)')));
}
}
}
$orig->decache();
$this->encache();
+
+ // commit our db transaction since we won't reach the COMMIT below
+ $this->query('COMMIT');
+ // @FIXME return true only if something changed (otherwise 0)
return true;
}
// commit our db transaction
$this->query('COMMIT');
+ // @FIXME return true only if something changed (otherwise 0)
return $result;
}
}
$adapter->showNotice();
$adapter->showNoticeAttachments();
- $adapter->showNoticeInfo();
- $adapter->showNoticeOptions();
+ $adapter->showNoticeFooter();
return false;
}
if (!$result) {
common_log_db_error($rm, 'INSERT', __FILE__);
+ $rm->query('ROLLBACK');
return false;
}
}
// This probably needs some work. For example with IPv6 you can easily generate new IPs...
- $this->client_ip = common_client_ip()[0] ?: common_client_ip()[1]; // [0] is proxy, [1] should be the real IP
+ $client_ip = common_client_ip();
+ $this->client_ip = $client_ip[0] ?: $client_ip[1]; // [0] is proxy, [1] should be the real IP
$this->failed_attempts = (int)$this->unauthed_user->getPref(self::FAILED_LOGIN_IP_SECTION, $this->client_ip);
switch (true) {
case $this->failed_attempts >= 5:
$replies = $stored->getReplies();
$tags = $stored->getTags();
+ if (!empty($nb->description)) {
+ $out->element('p',
+ array('class' => 'bookmark-description'),
+ $nb->description);
+ }
+
if (!empty($replies) || !empty($tags)) {
$out->elementStart('ul', array('class' => 'bookmark-tags'));
$out->elementEnd('ul');
}
- if (!empty($nb->description)) {
- $out->element('p',
- array('class' => 'bookmark-description'),
- $nb->description);
- }
}
}
.bookmark-tags li { display: inline; }
.bookmark h3 {
- margin: 0px 0px 8px 0px;
- line-height: 3em;
+ margin: 4px 0px 8px 0px;
}
.bookmark-notice-count {
.bookmark-tags {
clear: both;
- margin-bottom: 8px;
+ margin-bottom: 4px;
line-height: 1.6em;
}
* user or group Atom feeds.
*
* @param string $feed URL
- * @return boolean true if it matches
+ * @return boolean true if it matches, false if not a recognized local feed
+ * @throws exception if local entity does not exist
*/
- function recognizedFeed($feed)
+ protected function recognizedFeed($feed)
{
$matches = array();
+ // Simple mapping to local ID for user or group
if (preg_match('!/(\d+)\.atom$!', $feed, $matches)) {
$id = $matches[1];
$params = array('id' => $id, 'format' => 'atom');
- $userFeed = common_local_url('ApiTimelineUser', $params);
- $groupFeed = common_local_url('ApiTimelineGroup', $params);
- if ($feed == $userFeed) {
+ // Double-check against locally generated URLs
+ switch ($feed) {
+ case common_local_url('ApiTimelineUser', $params):
$user = User::getKV('id', $id);
- if (!$user) {
+ if (!$user instanceof User) {
// TRANS: Client exception. %s is a feed URL.
- throw new ClientException(sprintt(_m('Invalid hub.topic "%s". User does not exist.'),$feed));
- } else {
- return true;
+ throw new ClientException(sprintf(_m('Invalid hub.topic "%s". User does not exist.'),$feed));
}
- }
- if ($feed == $groupFeed) {
- $user = User_group::getKV('id', $id);
- if (!$user) {
+ return true;
+
+ case common_local_url('ApiTimelineGroup', $params):
+ $group = Local_group::getKV('group_id', $id);
+ if (!$group instanceof Local_group) {
// TRANS: Client exception. %s is a feed URL.
- throw new ClientException(sprintf(_m('Invalid hub.topic "%s". Group does not exist.'),$feed));
- } else {
- return true;
+ throw new ClientException(sprintf(_m('Invalid hub.topic "%s". Local_group does not exist.'),$feed));
}
+ return true;
}
- } else if (preg_match('!/(\d+)/lists/(\d+)/statuses\.atom$!', $feed, $matches)) {
+ common_debug("Feed was not recognized by any local User or Group Atom feed URLs: {$feed}");
+ return false;
+ }
+
+ // Profile lists are unique per user, so we need both IDs
+ if (preg_match('!/(\d+)/lists/(\d+)/statuses\.atom$!', $feed, $matches)) {
$user = $matches[1];
$id = $matches[2];
$params = array('user' => $user, 'id' => $id, 'format' => 'atom');
- $listFeed = common_local_url('ApiTimelineList', $params);
- if ($feed == $listFeed) {
+ // Double-check against locally generated URLs
+ switch ($feed) {
+ case common_local_url('ApiTimelineList', $params):
$list = Profile_list::getKV('id', $id);
$user = User::getKV('id', $user);
- if (!$list || !$user || $list->tagger != $user->id) {
+ if (!$list instanceof Profile_list || !$user instanceof User || $list->tagger != $user->id) {
// TRANS: Client exception. %s is a feed URL.
throw new ClientException(sprintf(_m('Invalid hub.topic %s; list does not exist.'),$feed));
- } else {
- return true;
}
+ return true;
}
- common_log(LOG_DEBUG, "Not a user, group or people tag feed? $feed $userFeed $groupFeed $listFeed");
+ common_debug("Feed was not recognized by any local Profile_list Atom feed URL: {$feed}");
+ return false;
}
- common_log(LOG_DEBUG, "LOST $feed");
+
+ common_debug("Unknown feed URL structure, can't match against local user, group or profile_list: {$feed}");
return false;
}
'sub_state' => array('type' => 'enum("subscribe","active","unsubscribe","inactive","nohub")', 'not null' => true, 'description' => 'subscription state'),
'sub_start' => array('type' => 'datetime', 'description' => 'subscription start'),
'sub_end' => array('type' => 'datetime', 'description' => 'subscription end'),
- 'last_update' => array('type' => 'datetime', 'not null' => true, 'description' => 'when this record was last updated'),
+ 'last_update' => array('type' => 'datetime', 'description' => 'when this record was last updated'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
),
'topic' => array('type' => 'varchar', 'not null' => true, 'length' => 255, 'description' => 'HubSub topic'),
'callback' => array('type' => 'varchar', 'not null' => true, 'length' => 255, 'description' => 'HubSub callback'),
'secret' => array('type' => 'text', 'description' => 'HubSub stored secret'),
- 'lease' => array('type' => 'int', 'not null' => true, 'description' => 'HubSub leasetime'),
+ 'lease' => array('type' => 'int', 'description' => 'HubSub leasetime'),
'sub_start' => array('type' => 'datetime', 'description' => 'subscription start'),
'sub_end' => array('type' => 'datetime', 'description' => 'subscription end'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
$osource->notice_id = $notice->id;
$osource->profile_uri = $oprofile->uri;
$osource->method = $method;
+ $osource->created = common_sql_now();
if ($osource->insert()) {
return true;
} else {