Commit b59df00c authored by hannes's avatar hannes

upload

parents
<?php
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
· ·
· ·
· Q V I T T E R ·
· ·
· http://github.com/hannesmannerheim/qvitter ·
· ·
· ·
· <o) ·
· /_//// ·
· (____/ ·
· (o< ·
· o> \\\\_\ ·
· \\) \____) ·
· ·
· ·
· ·
· Qvitter 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 three of the License or (at ·
· your option) any later version. ·
· ·
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
· WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
· ·
· Contact h@nnesmannerhe.im if you have any questions. ·
· ·
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
include 'settings.php';
header("Content-type: application/json; charset=utf-8");
if(substr($apiroot,-1) != '/') { $apiroot .= '/'; } // add slash if missing
// post requests
if(isset($_POST['postRequest'])) {
$query = http_build_query($_POST, '', '&');
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $apiroot.urldecode($_POST['postRequest']));
curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
session_write_close(); // fix problem with curling to local
$reply=curl_exec($ch);
curl_close($ch);
session_start();
// force ssl on our domain
if($forcessl) {
$reply = str_replace('http://'.$siterootdomain,'https://'.$siterootdomain,$reply);
}
print $reply;
}
// get requests
elseif(isset($_POST['getRequest'])) {
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $apiroot.$_POST['getRequest']);
if(isset($_POST['username'])) {
curl_setopt($ch, CURLOPT_USERPWD, $_POST['username'].":".$_POST['password']);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
session_write_close();
$reply=curl_exec($ch);
curl_close($ch);
session_start();
// force ssl on our domain
if($forcessl) {
$reply = str_replace('http:\/\/'.$siterootdomain,'https:\/\/'.$siterootdomain,$reply);
}
print $reply;
}
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
· ·
· (o> >o) ·
· \\\\_\ /_//// .
· \____) (____/ ·
· ·
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */?>
\ No newline at end of file
This diff is collapsed.
Qvitter
==========================================
* Author: Hannes Mannerheim (<h@nnesmannerhe.im>)
* Last mod.: August, 2013
* Version: 1
* Website: <http://beaneditor.org/>
* GitHub: <https://github.com/hannesmannerheim/qvitter>
Qvitter 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 three of the License or (at
your option) any later version.
Qvitter is distributed in hope that it will be useful but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILTY 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 Qvitter. If not, see <http://www.gnu.org/licenses/>.
Setup
-----
You need a webserver with PHP support.
Edit settings.php.
(Qvitter uses a slightly modified statusnet API. Some things will not work
if you connect to a site with standard API. Files are included if you want
to Qvitter-mod your Statusnet API.)
TODO
----
1. Join new external groups and follow new external users
2. Follow people on other instances
3. Auto suggest mentions
4. Register
5. Background image uploading/editing
6. Color theme
7. Auto url-shortening setting under queet box
10. Settings (e.g. don't show replies to people I don't follow)
11. Syntax-coloring in queet-box, maybe codemirror (worked nicely for ltr but not rtl text when I tried it)
12. Image/file upload, drag-n-drop!
13. Search users
14. Recommended users
15. Filters (hide queets containing strings, e.g. mute users)
18. Better responsive design
19. More languages
20. Queet-page
21. New api for serving _number_ of new items in several streams (to show number of new items in menu/history)
22. New "expand queet" api for getting conversation, retweets, favs and attachment in the same request
23. DMs
24. Node.js long polling server and an new api that serve aggregate of all polling users requests in one go
CHANGES TO API
--------------
* actions/apiattachment.php New api action
* actions/apistatusesfavs.php New api action
* actions/apicheckhub.php New api action (not used yet)
* actions/apiexternalprofileshow.php New api action
* lib/apiaction.php
- add urls to larger avatars
~LINE 213 $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
$twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() :
Avatar::defaultImage(AVATAR_STREAM_SIZE);
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
$twitter_user['profile_image_url_profile_size'] = ($avatar) ? $avatar->displayUrl() :
Avatar::defaultImage(AVATAR_PROFILE_SIZE);
$avatar = $profile->getOriginalAvatar();
$twitter_user['profile_image_url_original'] = ($avatar) ? $avatar->displayUrl() :
Avatar::defaultImage(AVATAR_PROFILE_SIZE);
$groups = $profile->getGroups();
$groups_count = 0; while($groups->fetch()) $groups_count++;
$twitter_user['groups_count'] = $groups_count;
- add the uri-field
~line 320 $twitter_status['uri'] = $notice->uri;
- show if a notices is favorited by auth_user
~line 345 if (isset($this->auth_user)) {
$this_profile = $this->auth_user->getProfile();
$twitter_status['favorited'] = $this->auth_user->hasFave($notice);
$twitter_status['repeated'] = $this_profile->hasRepeated($notice->id);
} else {
$twitter_status['favorited'] = false;
$twitter_status['repeated'] = false;
}
- show number of admins in group api
~line 420 $admins = $group->getAdmins();
$admin_count = 0; while($admins->fetch()) $admin_count++;
$twitter_group['admin_count'] = $admin_count;
- to be able to get group profile by uri.
- hackish though, because if uri get-var is sent, it will discard the id get var
- (but id still needs to be sent and be non-numerical, so I do "?id=foo&uri={uri}")
- should be possible to only supply uri get var, but I was lazy... sry
~line 1565 } else if ($this->arg('uri')) {
return User_group::staticGet('uri', urldecode($this->arg('uri')));
* lib/router.php
- add routing for new api actions
~line 467: $m->connect('api/statuses/favs/:id.json',
array('action' => 'ApiStatusesFavs',
'id' => '[0-9]+'));
$m->connect('api/attachment/:id.json',
array('action' => 'ApiAttachment',
'id' => '[0-9]+'));
$m->connect('api/checkhub.json',
array('action' => 'ApiCheckHub'));
$m->connect('api/externalprofile/show.json',
array('action' => 'ApiExternalProfileShow'));
- also, tags need regexp to work with unicode charachters, e.g. farsi and arabic:
$m->connect('api/statusnet/tags/timeline/:tag.:format',
array('action' => 'ApiTimelineTag',
'tag' => self::REGEX_TAG,
'format' => '(xml|json|rss|atom|as)'));
* acitons/apiconversation.php
- I didn't always get Profile::current() to show me the auth user's profile, so I changed it to the normal $this->auth_user used in other api actions
~ line 80: if(isset($this->auth_user)) {
$profile = $this->auth_user->getProfile();
}
else {
$profile = null;
}
*actions/apitimelineuser.php
- this api did only return the public user timeline, not the auth user's.
- e.g. it did not show notices from people who post to "my colleques at quitter"
- changed to return timeline according to which auth user is requesting
~ line 238 $user_profile = $this->user->getProfile();
if(isset($this->auth_user)) {
$auth_user_profile = $this->auth_user->getProfile();
}
else {
$auth_user_profile = null;
}
$stream = new ProfileNoticeStream($user_profile, $auth_user_profile);
$notice = $stream->getNotices(($this->page-1) * $this->count,
$this->count + 1,
$this->since_id,
$this->max_id);
* search.json
- changed response to normal twitter format, maybe I should have created a new api action for that,
- but... i don't see the point in having a special format for searches, it should be same as other streams
* actions/timelinetags.php
- added max_id and since_id
~line 179 $notice = Notice_tag::getStream(
$this->tag,
($this->page - 1) * $this->count,
$this->count + 1,
$this->since_id,
$this->max_id
);
* actions/apistatusesupdate.php
- we don't want statuses to shorten if sent through the api
~ line 290: //$status_shortened = $this->auth_user->shortenlinks($this->status);
$status_shortened = $this->status;
* classes/Notice.php
- to _not_ shorten urls sent through api, we need to comment out this also
~ line 352 // if ($user) {
// // Use the local user's shortening preferences, if applicable.
// $final = $user->shortenLinks($content);
// } else {
// $final = common_shorten_links($content);
// }
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Show a notice's attachment
*
* 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 API
* @package StatusNet
* @author Hannes Mannerheim <h@nnesmannerhe.im>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
require_once INSTALLDIR . '/lib/mediafile.php';
/**
* Show a notice's attachment
*
*/
class ApiAttachmentAction extends ApiAuthAction
{
const MAXCOUNT = 100;
var $original = null;
var $cnt = self::MAXCOUNT;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
{
parent::prepare($args);
return true;
}
/**
* Handle the request
*
* Make a new notice for the update, save it, and show it
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
parent::handle($args);
$file = new File();
$file->selectAdd(); // clears it
$file->selectAdd('url');
$file->id = $this->trimmed('id');
$url = $file->fetchAll('url');
$file_txt = '';
if(strstr($url[0],'.html')) {
$file_txt['txt'] = file_get_contents(str_replace('://quitter.se','://127.0.0.1',$url[0]));
$file_txt['body_start'] = strpos($file_txt['txt'],'<body>')+6;
$file_txt['body_end'] = strpos($file_txt['txt'],'</body>');
$file_txt = substr($file_txt['txt'],$file_txt['body_start'],$file_txt['body_end']-$file_txt['body_start']);
}
$this->initDocument('json');
$this->showJsonObjects($file_txt);
$this->endDocument('json');
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Show a notice's attachment
*
* 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 API
* @package StatusNet
* @author Hannes Mannerheim <h@nnesmannerhe.im>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
require_once INSTALLDIR . '/lib/mediafile.php';
/**
* Check if a url have a push-hub, i.e. if it is possible to subscribe
*
*/
class ApiCheckHubAction extends ApiAuthAction
{
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
{
parent::prepare($args);
$this->url = urldecode($args['url']);
if (!$this->url) {
$this->clientError(_('No URL.'), 403, 'json');
return;
}
if (!Validate::uri(
$this->url, array(
'allowed_schemes' =>
array('http', 'https')
)
)) {
$this->clientError(_('Invalid URL.'), 403, 'json');
return;
}
return true;
}
/**
* Handle the request
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
{
$discover = new FeedDiscovery();
try {
$feeduri = $discover->discoverFromURL($this->url);
if($feeduri) {
$huburi = $discover->getHubLink();
}
} catch (FeedSubNoFeedException $e) {
$this->clientError(_('No feed found'), 403, 'json');
return;
} catch (FeedSubBadResponseException $e) {
$this->clientError(_('No hub found'), 403, 'json');
return;
}
$hub_status = array();
if ($huburi) {
$hub_status = array('huburi' => $huburi);
}
$this->initDocument('json');
$this->showJsonObjects($hub_status);
$this->endDocument('json');
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
}
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Show a stream of notices in a particular conversation
*
* PHP version 5
*
* 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 API
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
require_once INSTALLDIR . '/lib/apiauth.php';
/**
* Show a stream of notices in a particular conversation
*
* @category API
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class ApiconversationAction extends ApiAuthAction
{
protected $conversation = null;
protected $notices = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$convId = $this->trimmed('id');
if (empty($convId)) {
// TRANS: Client exception thrown when no conversation ID is given.
throw new ClientException(_('No conversation ID.'));
}
$this->conversation = Conversation::staticGet('id', $convId);
if (empty($this->conversation)) {
// TRANS: Client exception thrown when referring to a non-existing conversation ID (%d).
throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId),
404);
}
// $profile = Profile::current();
if(isset($this->auth_user)) {
$profile = $this->auth_user->getProfile();
}
else {
$profile = null;
}
$stream = new ConversationNoticeStream($convId, $profile);
$notice = $stream->getNotices(($this->page-1) * $this->count,
$this->count,
$this->since_id,
$this->max_id);
$this->notices = $notice->fetchAll();
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
{
$sitename = common_config('site', 'name');
// TRANS: Title for conversion timeline.
$title = _m('TITLE', 'Conversation');
$id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format));
$link = common_local_url('conversation', array('id' => $this->conversation->id));
$self = $id;
switch($this->format) {
case 'xml':
$this->showXmlTimeline($this->notices);
break;
case 'rss':
$this->showRssTimeline(
$this->notices,
$title,
$link,
null,
null,
null,
$self
);
break;
case 'atom':
header('Content-Type: application/atom+xml; charset=utf-8');
$atom = new AtomNoticeFeed($this->auth_user);
$atom->setId($id);
$atom->setTitle($title);
$atom->setUpdated('now');
$atom->addLink($link);
$atom->setSelfLink($self);
$atom->addEntryFromNotices($this->notices);
$this->raw($atom->getString());
break;
case 'json':
$this->showJsonTimeline($this->notices);
break;
case 'as':
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
$doc = new ActivityStreamJSONDocument($this->auth_user);
$doc->setTitle($title);
$doc->addLink($link, 'alternate', 'text/html');
$doc->addItemsFromNotices($this->notices);
$this->raw($doc->asString());
break;
default:
// TRANS: Client error displayed when coming across a non-supported API method.
$this->clientError(_('API method not found.'), $code = 404);
break;
}
}
/**
* Return true if read only.
*