remove twitter-specific code

master
Andrew Dolgov 12 years ago
parent ec78654f4e
commit 304aadb907

@ -110,8 +110,7 @@
$update_methods = array(
0 => __("Default"),
1 => __("Magpie"),
2 => __("SimplePie"),
3 => __("Twitter OAuth"));
2 => __("SimplePie"));
if (DEFAULT_UPDATE_METHOD == "1") {
$update_methods[0] .= ' (SimplePie)';

@ -24,14 +24,6 @@ class Pref_Feeds extends Handler_Protected {
return;
}
function remtwitterinfo() {
db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
WHERE id = " . $_SESSION['uid']);
return;
}
private function get_category_items($cat_id) {
$show_empty_cats = $_REQUEST['mode'] != 2 &&
get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
@ -1603,35 +1595,6 @@ class Pref_Feeds extends Handler_Protected {
print "</div>"; #pane
if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
$result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
id = " . $_SESSION['uid']);
$is_registered = db_fetch_result($result, 0, "cid") != 0;
if (!$is_registered) {
print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
} else {
print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
}
print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
__("Register with Twitter.com")."</button>";
print " ";
print "<button dojoType=\"dijit.form.Button\"
onclick=\"return clearTwitterCredentials()\">".
__("Clear stored credentials")."</button>";
print "</div>"; # pane
}
print "</div>"; #container
}

@ -790,10 +790,6 @@ class RPC extends Handler_Protected {
$pass = db_escape_string($_REQUEST['pass']);
$need_auth = db_escape_string($_REQUEST['need_auth']) != "";
$result = db_query($this->link, "SELECT twitter_oauth FROM ttrss_users
WHERE id = ".$_SESSION['uid']);
$has_oauth = db_fetch_result($result, 0, 'twitter_oauth') != "";
foreach ($feeds as $feed) {
$feed = trim($feed);
@ -801,12 +797,7 @@ WHERE id = ".$_SESSION['uid']);
db_query($this->link, "BEGIN");
if (!$need_auth || !$has_oauth || strpos($url, '://api.twitter.com')
=== false) {
$update_method = 0;
} else {
$update_method = 3;
}
$update_method = 0;
if ($cat_id == "0" || !$cat_id) {
$cat_qpart = "NULL";

@ -162,15 +162,6 @@
// These two options enable SMTP authentication when sending
// outgoing mail. Only used with SMTP_HOST
// ************************************
// *** Twitter integration settings ***
// ************************************
define('CONSUMER_KEY', '');
define('CONSUMER_SECRET', '');
// Your OAuth instance authentication information for Twitter, visit
// http://twitter.com/oauth_clients to register your instance.
// ***************************************
// *** Other settings (less important) ***
// ***************************************

@ -1782,32 +1782,20 @@
$update_method = 0;
$result = db_query($link, "SELECT twitter_oauth FROM ttrss_users
WHERE id = ".$_SESSION['uid']);
if (!fetch_file_contents($url, false, $auth_login, $auth_pass))
return array("code" => 5, "message" => $fetch_last_error);
$has_oauth = db_fetch_result($result, 0, 'twitter_oauth');
if (!$need_auth || !$has_oauth || strpos($url, '://api.twitter.com') === false) {
if (!fetch_file_contents($url, false, $auth_login, $auth_pass))
return array("code" => 5, "message" => $fetch_last_error);
if (url_is_html($url, $auth_login, $auth_pass)) {
$feedUrls = get_feeds_from_html($url, $auth_login, $auth_pass);
if (count($feedUrls) == 0) {
return array("code" => 3);
} else if (count($feedUrls) > 1) {
return array("code" => 4);
}
//use feed url as new URL
$url = key($feedUrls);
if (url_is_html($url, $auth_login, $auth_pass)) {
$feedUrls = get_feeds_from_html($url, $auth_login, $auth_pass);
if (count($feedUrls) == 0) {
return array("code" => 3);
} else if (count($feedUrls) > 1) {
return array("code" => 4);
}
//use feed url as new URL
$url = key($feedUrls);
}
} else {
if (!fetch_twitter_rss($link, $url, $_SESSION['uid']))
return array("code" => 5);
$update_method = 3;
}
if ($cat_id == "0" || !$cat_id) {
$cat_qpart = "NULL";
} else {

@ -157,58 +157,6 @@
} // function update_daemon_common
function fetch_twitter_rss($link, $url, $owner_uid) {
require_once 'lib/tmhoauth/tmhOAuth.php';
require_once "lib/magpierss/rss_fetch.inc";
require_once 'lib/magpierss/rss_utils.inc';
$result = db_query($link, "SELECT twitter_oauth FROM ttrss_users
WHERE id = $owner_uid");
$access_token = json_decode(db_fetch_result($result, 0, 'twitter_oauth'), true);
$url_escaped = db_escape_string($url);
if ($access_token) {
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => CONSUMER_KEY,
'consumer_secret' => CONSUMER_SECRET,
'user_token' => $access_token['oauth_token'],
'user_secret' => $access_token['oauth_token_secret'],
));
$code = $tmhOAuth->request('GET', $url,
convertUrlQuery(parse_url($url, PHP_URL_QUERY)));
if ($code == 200) {
$content = $tmhOAuth->response['response'];
define('MAGPIE_CACHE_ON', false);
$rss = new MagpieRSS($content, MAGPIE_OUTPUT_ENCODING,
MAGPIE_INPUT_ENCODING, MAGPIE_DETECT_ENCODING );
return $rss;
} else {
db_query($link, "UPDATE ttrss_feeds
SET last_error = 'OAuth authorization failed ($code).'
WHERE feed_url = '$url_escaped' AND owner_uid = $owner_uid");
}
} else {
db_query($link, "UPDATE ttrss_feeds
SET last_error = 'OAuth information not found.'
WHERE feed_url = '$url_escaped' AND owner_uid = $owner_uid");
return false;
}
}
function update_rss_feed($link, $feed, $ignore_daemon = false, $no_cache = false,
$override_url = false) {
@ -317,9 +265,7 @@
$cache_age = (is_null($last_updated) || $last_updated == '1970-01-01 00:00:00') ?
-1 : get_feed_update_interval($link, $feed) * 60;
if ($update_method == 3) {
$rss = fetch_twitter_rss($link, $fetch_url, $owner_uid);
} else if ($update_method == 1) {
if ($update_method == 1) {
define('MAGPIE_CACHE_AGE', $cache_age);
define('MAGPIE_CACHE_ON', !$no_cache);

@ -1,3 +1,3 @@
<?php # This file has been generated at: Thu Aug 23 23:48:15 MSK 2012
<?php # This file has been generated at: Fri Sep 7 10:20:51 MSK 2012
define('GENERATED_CONFIG_CHECK', 26);
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'SINGLE_USER_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_MODULES', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'DEFAULT_UPDATE_METHOD', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_EXPIRE_TIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_HOST', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'CONSUMER_KEY', 'CONSUMER_SECRET', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'FEEDBACK_URL', 'ARTICLE_BUTTON_PLUGINS', 'CONFIG_VERSION'); ?>
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'SINGLE_USER_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_MODULES', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'DEFAULT_UPDATE_METHOD', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_EXPIRE_TIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_HOST', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'FEEDBACK_URL', 'ARTICLE_BUTTON_PLUGINS', 'CONFIG_VERSION'); ?>

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -1,76 +0,0 @@
# tmhOAuth
An OAuth 1.0A library written in PHP by @themattharris, specifically for use
with the Twitter API.
**Disclaimer**: This project is a work in progress and may contain bugs.
## Goals
- Support OAuth 1.0A
- Use Authorisation headers instead of query string or POST parameters
- Allow uploading of images
- Provide enough information to assist with debugging
## Dependancies
The library has been tested with PHP 5.3+ and relies on CURL and hash_hmac. The
vast majority of hosting providers include these libraries and run with PHP 5.1+.
The code makes use of hash_hmac, which was introduced in PHP 5.1.2. If you version
of PHP is lower than this you should ask your hosting provider for an update.
## Usage
This will be built out later but for the moment review the examples for ways
the library can be used. Each example contains instructions on how to use it
## Change History
0.4 03 March 2011
Fixed handling of parameters when using DELETE. Thanks to yusuke for reporting
Fixed php_self to handle port numbers other than 80/443. Props: yusuke
Updated function pr to use pre only when not running in CLI mode
Add support for proxy servers. Props juanchorossi
Function request now returns the HTTP status code. Props: kronenthaler
Documentation fixes for xAuth. Props: 140dev
Some minor code formatting changes
0.3 28 September 2010
Moved entities rendering into the library
0.2 17 September 2010
Added support for the Streaming API
0.14 17 September 2010
Fixed authorisation header for use with OAuth Echo
0.13 17 September 2010
Added use_ssl configuration parameter
Fixed config array typo
Removed v from the config
Remove protocol from the host (configured by use_ssl)
Added include for easier debugging
0.12 17 September 2010
Moved curl options to config
Added the ability for curl to follow redirects, default false
0.11 17 September 2010
Fixed a bug in the GET requests
0.1 26 August 2010
Initial beta version
## Community
License: Apache 2 (see included LICENSE file)
Follow me on Twitter: <http://twitter.com/themattharris>
Check out the Twitter Developer Resources: <http://dev.twitter.com>
## To Do
- Add good behavior logic to the Streaming API handler - i.e. on disconnect back off
- Add demo of responsible rate limit handling
- Async Curl support
- Split Utilities functions out

@ -1,726 +0,0 @@
<?php
/**
* tmhOAuth
*
* An OAuth 1.0A library written in PHP.
* The library supports file uploading using multipart/form as well as general
* REST requests. OAuth authentication is sent using the an Authorization Header.
*
* @author themattharris
* @version 0.4
*
* 03 March 2011
*/
class tmhOAuth {
/**
* Creates a new tmhOAuth object
*
* @param string $config, the configuration to use for this request
*/
function __construct($config) {
$this->params = array();
$this->auto_fixed_time = false;
// default configuration options
$this->config = array_merge(
array(
'consumer_key' => '',
'consumer_secret' => '',
'user_token' => '',
'user_secret' => '',
'use_ssl' => true,
'host' => 'api.twitter.com',
'debug' => false,
'force_nonce' => false,
'nonce' => false, // used for checking signatures. leave as false for auto
'force_timestamp' => false,
'timestamp' => false, // used for checking signatures. leave as false for auto
'oauth_version' => '1.0',
// you probably don't want to change any of these curl values
'curl_connecttimeout' => 30,
'curl_timeout' => 10,
// for security you may want to set this to TRUE. If you do you need
// to install the servers certificate in your local certificate store.
'curl_ssl_verifypeer' => false,
'curl_followlocation' => false, // whether to follow redirects or not
// support for proxy servers
'curl_proxy' => false, // really you don't want to use this if you are using streaming
'curl_proxyuserpwd' => false, // format username:password for proxy, if required
// streaming API
'is_streaming' => false,
'streaming_eol' => "\r\n",
'streaming_metrics_interval' => 60,
),
$config
);
}
/**
* Generates a random OAuth nonce.
* If 'force_nonce' is true a nonce is not generated and the value in the configuration will be retained.
*
* @param string $length how many characters the nonce should be before MD5 hashing. default 12
* @param string $include_time whether to include time at the beginning of the nonce. default true
* @return void
*/
private function create_nonce($length=12, $include_time=true) {
if ($this->config['force_nonce'] == false) {
$sequence = array_merge(range(0,9), range('A','Z'), range('a','z'));
$length = $length > count($sequence) ? count($sequence) : $length;
shuffle($sequence);
$this->config['nonce'] = md5(substr(microtime() . implode($sequence), 0, $length));
}
}
/**
* Generates a timestamp.
* If 'force_timestamp' is true a nonce is not generated and the value in the configuration will be retained.
*
* @return void
*/
private function create_timestamp() {
$this->config['timestamp'] = ($this->config['force_timestamp'] == false ? time() : $this->config['timestamp']);
}
/**
* Encodes the string or array passed in a way compatible with OAuth.
* If an array is passed each array value will will be encoded.
*
* @param mixed $data the scalar or array to encode
* @return $data encoded in a way compatible with OAuth
*/
private function safe_encode($data) {
if (is_array($data)) {
return array_map(array($this, 'safe_encode'), $data);
} else if (is_scalar($data)) {
return str_ireplace(
array('+', '%7E'),
array(' ', '~'),
rawurlencode($data)
);
} else {
return '';
}
}
/**
* Decodes the string or array from it's URL encoded form
* If an array is passed each array value will will be decoded.
*
* @param mixed $data the scalar or array to decode
* @return $data decoded from the URL encoded form
*/
private function safe_decode($data) {
if (is_array($data)) {
return array_map(array($this, 'safe_decode'), $data);
} else if (is_scalar($data)) {
return rawurldecode($data);
} else {
return '';
}
}
/**
* Returns an array of the standard OAuth parameters.
*
* @return array all required OAuth parameters, safely encoded
*/
private function get_defaults() {
$defaults = array(
'oauth_version' => $this->config['oauth_version'],
'oauth_nonce' => $this->config['nonce'],
'oauth_timestamp' => $this->config['timestamp'],
'oauth_consumer_key' => $this->config['consumer_key'],
'oauth_signature_method' => 'HMAC-SHA1',
);
// include the user token if it exists
if ( $this->config['user_token'] )
$defaults['oauth_token'] = $this->config['user_token'];
// safely encode
foreach ($defaults as $k => $v) {
$_defaults[$this->safe_encode($k)] = $this->safe_encode($v);
}
return $_defaults;
}
/**
* Extracts and decodes OAuth parameters from the passed string
*
* @param string $body the response body from an OAuth flow method
* @return array the response body safely decoded to an array of key => values
*/
function extract_params($body) {
$kvs = explode('&', $body);
$decoded = array();
foreach ($kvs as $kv) {
$kv = explode('=', $kv, 2);
$kv[0] = $this->safe_decode($kv[0]);
$kv[1] = $this->safe_decode($kv[1]);
$decoded[$kv[0]] = $kv[1];
}
return $decoded;
}
/**
* Prepares the HTTP method for use in the base string by converting it to
* uppercase.
*
* @param string $method an HTTP method such as GET or POST
* @return void value is stored to a class variable
* @author themattharris
*/
private function prepare_method($method) {
$this->method = strtoupper($method);
}
/**
* Prepares the URL for use in the base string by ripping it apart and
* reconstructing it.
*
* @param string $url the request URL
* @return void value is stored to a class variable
* @author themattharris
*/
private function prepare_url($url) {
$parts = parse_url($url);
$port = @$parts['port'];
$scheme = $parts['scheme'];
$host = $parts['host'];
$path = @$parts['path'];
$port or $port = ($scheme == 'https') ? '443' : '80';
if (($scheme == 'https' && $port != '443')
|| ($scheme == 'http' && $port != '80')) {
$host = "$host:$port";
}
$this->url = "$scheme://$host$path";
}
/**
* Prepares all parameters for the base string and request.
* Multipart parameters are ignored as they are not defined in the specification,
* all other types of parameter are encoded for compatibility with OAuth.
*
* @param array $params the parameters for the request
* @return void prepared values are stored in class variables
*/
private function prepare_params($params) {
// do not encode multipart parameters, leave them alone
if ($this->config['multipart']) {
$this->request_params = $params;
$params = array();
}
// signing parameters are request parameters + OAuth default parameters
$this->signing_params = array_merge($this->get_defaults(), (array)$params);
// Remove oauth_signature if present
// Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
if (isset($this->signing_params['oauth_signature'])) {
unset($this->signing_params['oauth_signature']);
}
// Parameters are sorted by name, using lexicographical byte value ordering.
// Ref: Spec: 9.1.1 (1)
uksort($this->signing_params, 'strcmp');
// encode. Also sort the signed parameters from the POST parameters
foreach ($this->signing_params as $k => $v) {
$k = $this->safe_encode($k);
$v = $this->safe_encode($v);
$_signing_params[$k] = $v;
$kv[] = "{$k}={$v}";
}
// auth params = the default oauth params which are present in our collection of signing params
$this->auth_params = array_intersect_key($this->get_defaults(), $_signing_params);
if (isset($_signing_params['oauth_callback'])) {
$this->auth_params['oauth_callback'] = $_signing_params['oauth_callback'];
unset($_signing_params['oauth_callback']);
}
// request_params is already set if we're doing multipart, if not we need to set them now
if ( ! $this->config['multipart'])
$this->request_params = array_diff_key($_signing_params, $this->get_defaults());
// create the parameter part of the base string
$this->signing_params = implode('&', $kv);
}
/**
* Prepares the OAuth signing key
*
* @return void prepared signing key is stored in a class variables
*/
private function prepare_signing_key() {
$this->signing_key = $this->safe_encode($this->config['consumer_secret']) . '&' . $this->safe_encode($this->config['user_secret']);
}
/**
* Prepare the base string.
* Ref: Spec: 9.1.3 ("Concatenate Request Elements")
*
* @return void prepared base string is stored in a class variables
*/
private function prepare_base_string() {
$base = array(
$this->method,
$this->url,
$this->signing_params
);
$this->base_string = implode('&', $this->safe_encode($base));
}
/**
* Prepares the Authorization header
*
* @return void prepared authorization header is stored in a class variables
*/
private function prepare_auth_header() {
$this->headers = array();
uksort($this->auth_params, 'strcmp');
foreach ($this->auth_params as $k => $v) {
$kv[] = "{$k}=\"{$v}\"";
}
$this->auth_header = 'OAuth ' . implode(', ', $kv);
$this->headers[] = 'Authorization: ' . $this->auth_header;
}
/**
* Signs the request and adds the OAuth signature. This runs all the request
* parameter preparation methods.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $useauth whether to use authentication when making the request.
*/
private function sign($method, $url, $params, $useauth) {
$this->prepare_method($method);
$this->prepare_url($url);
$this->prepare_params($params);
// we don't sign anything is we're not using auth
if ($useauth) {
$this->prepare_base_string();
$this->prepare_signing_key();
$this->auth_params['oauth_signature'] = $this->safe_encode(
base64_encode(
hash_hmac(
'sha1', $this->base_string, $this->signing_key, true
)));
$this->prepare_auth_header();
}
}
/**
* Make an HTTP request using this library. This method doesn't return anything.
* Instead the response should be inspected directly.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $useauth whether to use authentication when making the request. Default true.
* @param string $multipart whether this request contains multipart data. Default false
*/
function request($method, $url, $params=array(), $useauth=true, $multipart=false) {
$this->config['multipart'] = $multipart;
$this->create_nonce();
$this->create_timestamp();
$this->sign($method, $url, $params, $useauth);
return $this->curlit($multipart);
}
/**
* Make an HTTP request using this library. This method is different to 'request'
* because on a 401 error it will retry the request.
*
* When a 401 error is returned it is possible the timestamp of the client is
* too different to that of the API server. In this situation it is recommended
* the request is retried with the OAuth timestamp set to the same as the API
* server. This method will automatically try that technique.
*
* This method doesn't return anything. Instead the response should be
* inspected directly.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $useauth whether to use authentication when making the request. Default true.
* @param string $multipart whether this request contains multipart data. Default false
*/
function auto_fix_time_request($method, $url, $params=array(), $useauth=true, $multipart=false) {
$this->request($method, $url, $params, $useauth, $multipart);
// if we're not doing auth the timestamp isn't important
if ( ! $useauth)
return;
// some error that isn't a 401
if ($this->response['code'] != 401)
return;
// some error that is a 401 but isn't because the OAuth token and signature are incorrect
// TODO: this check is horrid but helps avoid requesting twice when the username and password are wrong
if (stripos($this->response['response'], 'password') !== false)
return;
// force the timestamp to be the same as the Twitter servers, and re-request
$this->auto_fixed_time = true;
$this->config['force_timestamp'] = true;
$this->config['timestamp'] = strtotime($this->response['headers']['date']);
$this->request($method, $url, $params, $useauth, $multipart);
}
/**
* Make a long poll HTTP request using this library. This method is
* different to the other request methods as it isn't supposed to disconnect
*
* Using this method expects a callback which will receive the streaming
* responses.
*
* @param string $method the HTTP method being used. e.g. POST, GET, HEAD etc
* @param string $url the request URL without query string parameters
* @param array $params the request parameters as an array of key=value pairs
* @param string $callback the callback function to stream the buffer to.
*/
function streaming_request($method, $url, $params=array(), $callback='') {
if ( ! empty($callback) ) {
if ( ! function_exists($callback) ) {
return false;
}
$this->config['streaming_callback'] = $callback;
}
$this->metrics['start'] = time();
$this->metrics['interval_start'] = $this->metrics['start'];
$this->metrics['tweets'] = 0;
$this->metrics['last_tweets'] = 0;
$this->metrics['bytes'] = 0;
$this->metrics['last_bytes'] = 0;
$this->config['is_streaming'] = true;
$this->request($method, $url, $params);
}
/**
* Handles the updating of the current Streaming API metrics.
*/
function update_metrics() {
$now = time();
if (($this->metrics['interval_start'] + $this->config['streaming_metrics_interval']) > $now)
return false;
$this->metrics['tps'] = round( ($this->metrics['tweets'] - $this->metrics['last_tweets']) / $this->config['streaming_metrics_interval'], 2);
$this->metrics['bps'] = round( ($this->metrics['bytes'] - $this->metrics['last_bytes']) / $this->config['streaming_metrics_interval'], 2);
$this->metrics['last_bytes'] = $this->metrics['bytes'];
$this->metrics['last_tweets'] = $this->metrics['tweets'];
$this->metrics['interval_start'] = $now;
return $this->metrics;
}
/**
* Utility function to create the request URL in the requested format
*
* @param string $request the API method without extension
* @param string $format the format of the response. Default json. Set to an empty string to exclude the format
* @return string the concatenation of the host, API version, API method and format
*/
function url($request, $format='json') {
$format = strlen($format) > 0 ? ".$format" : '';
$proto = $this->config['use_ssl'] ? 'https:/' : 'http:/';
// backwards compatibility with v0.1
if (isset($this->config['v']))
$this->config['host'] = $this->config['host'] . '/' . $this->config['v'];
return implode('/', array(
$proto,
$this->config['host'],
$request . $format
));
}
/**
* Utility function to parse the returned curl headers and store them in the
* class array variable.
*
* @param object $ch curl handle
* @param string $header the response headers
* @return the string length of the header
*/
private function curlHeader($ch, $header) {
$i = strpos($header, ':');
if ( ! empty($i) ) {
$key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
$value = trim(substr($header, $i + 2));
$this->response['headers'][$key] = $value;
}
return strlen($header);
}
/**
* Utility function to parse the returned curl buffer and store them until
* an EOL is found. The buffer for curl is an undefined size so we need
* to collect the content until an EOL is found.
*
* This function calls the previously defined streaming callback method.
*
* @param object $ch curl handle
* @param string $data the current curl buffer
*/
private function curlWrite($ch, $data) {
$l = strlen($data);
if (strpos($data, $this->config['streaming_eol']) === false) {
$this->buffer .= $data;
return $l;
}
$buffered = explode($this->config['streaming_eol'], $data);
$content = $this->buffer . $buffered[0];
$this->metrics['tweets']++;
$this->metrics['bytes'] += strlen($content);
if ( ! function_exists($this->config['streaming_callback']))
return 0;
$metrics = $this->update_metrics();
$stop = call_user_func(
$this->config['streaming_callback'],
$content,
strlen($content),
$metrics
);
$this->buffer = $buffered[1];
if ($stop)
return 0;
return $l;
}
/**
* Makes a curl request. Takes no parameters as all should have been prepared
* by the request method
*
* @return void response data is stored in the class variable 'response'
*/
private function curlit() {
// method handling
switch ($this->method) {
case 'POST':
break;
default:
// GET, DELETE request so convert the parameters to a querystring
if ( ! empty($this->request_params)) {
foreach ($this->request_params as $k => $v) {
// Multipart params haven't been encoded yet.
// Not sure why you would do a multipart GET but anyway, here's the support for it
if ($this->config['multipart']) {
$params[] = $this->safe_encode($k) . '=' . $this->safe_encode($v);
} else {
$params[] = $k . '=' . $v;
}
}
$qs = implode('&', $params);
$this->url = strlen($qs) > 0 ? $this->url . '?' . $qs : $this->url;
$this->request_params = array();
}
break;
}
if (@$this->config['prevent_request'])
return;
// configure curl
$c = curl_init();
curl_setopt($c, CURLOPT_USERAGENT, "themattharris' HTTP Client");
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, $this->config['curl_connecttimeout']);
curl_setopt($c, CURLOPT_TIMEOUT, $this->config['curl_timeout']);
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, $this->config['curl_ssl_verifypeer']);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, $this->config['curl_followlocation']);
curl_setopt($c, CURLOPT_PROXY, $this->config['curl_proxy']);
curl_setopt($c, CURLOPT_URL, $this->url);
// process the headers
curl_setopt($c, CURLOPT_HEADERFUNCTION, array($this, 'curlHeader'));
curl_setopt($c, CURLOPT_HEADER, FALSE);
curl_setopt($c, CURLINFO_HEADER_OUT, true);
if ($this->config['curl_proxyuserpwd'] !== false)
curl_setopt($c, CURLOPT_PROXYUSERPWD, $this->config['curl_proxyuserpwd']);
if ($this->config['is_streaming']) {
// process the body
$this->response['content-length'] = 0;
curl_setopt($c, CURLOPT_TIMEOUT, 0);
curl_setopt($c, CURLOPT_WRITEFUNCTION, array($this, 'curlWrite'));
}
switch ($this->method) {
case 'GET':
break;
case 'POST':
curl_setopt($c, CURLOPT_POST, TRUE);
break;
default:
curl_setopt($c, CURLOPT_CUSTOMREQUEST, $this->method);
}
if ( ! empty($this->request_params) ) {
// if not doing multipart we need to implode the parameters
if ( ! $this->config['multipart'] ) {
foreach ($this->request_params as $k => $v) {
$ps[] = "{$k}={$v}";
}
$this->request_params = implode('&', $ps);
}
curl_setopt($c, CURLOPT_POSTFIELDS, $this->request_params);
} else {
// CURL will set length to -1 when there is no data, which breaks Twitter
$this->headers[] = 'Content-Type:';
$this->headers[] = 'Content-Length:';
}
// CURL defaults to setting this to Expect: 100-Continue which Twitter rejects
$this->headers[] = 'Expect:';
if ( ! empty($this->headers))
curl_setopt($c, CURLOPT_HTTPHEADER, $this->headers);
// do it!
$response = curl_exec($c);
$code = curl_getinfo($c, CURLINFO_HTTP_CODE);
$info = curl_getinfo($c);
curl_close($c);
// store the response
$this->response['code'] = $code;
$this->response['response'] = $response;
$this->response['info'] = $info;
return $code;
}
/**
* Debug function for printing the content of an object
*
* @param mixes $obj
*/
function pr($obj) {
$cli = (PHP_SAPI == 'cli' && empty($_SERVER['REMOTE_ADDR']));
if (!$cli)
echo '<pre style="word-wrap: break-word">';
if ( is_object($obj) )
print_r($obj);
elseif ( is_array($obj) )
print_r($obj);
else
echo $obj;
if (!$cli)
echo '</pre>';
}
/**
* Returns the current URL. This is instead of PHP_SELF which is unsafe
*
* @param bool $dropqs whether to drop the querystring or not. Default true
* @return string the current URL
*/
function php_self($dropqs=true) {
$url = sprintf('%s://%s%s',
empty($_SERVER['HTTPS']) ? 'http' : 'https',
$_SERVER['SERVER_NAME'],
$_SERVER['REQUEST_URI']
);
$parts = parse_url($url);
$port = $_SERVER['SERVER_PORT'];
$scheme = $parts['scheme'];
$host = $parts['host'];
$path = @$parts['path'];
$qs = @$parts['query'];
$port or $port = ($scheme == 'https') ? '443' : '80';
if (($scheme == 'https' && $port != '443')
|| ($scheme == 'http' && $port != '80')) {
$host = "$host:$port";
}
$url = "$scheme://$host$path";
if ( ! $dropqs)
return "{$url}?{$qs}";
else
return $url;
}
/**
* Entifies the tweet using the given entities element
*
* @param array $tweet the json converted to normalised array
* @return the tweet text with entities replaced with hyperlinks
*/
function entify($tweet) {
$keys = array();
$replacements = array();
$is_retweet = false;
if (isset($tweet['retweeted_status'])) {
$tweet = $tweet['retweeted_status'];
$is_retweet = true;
}
if (!isset($tweet['entities'])) {
return $tweet['text'];
}
// prepare the entities
foreach ($tweet['entities'] as $type => $things) {
foreach ($things as $entity => $value) {
$tweet_link = "<a href=\"http://twitter.com/{$value['screen_name']}/statuses/{$tweet['id']}\">{$tweet['created_at']}</a>";
switch ($type) {
case 'hashtags':
$href = "<a href=\"http://search.twitter.com/search?q=%23{$value['text']}\">#{$value['text']}</a>";
break;
case 'user_mentions':
$href = "@<a href=\"http://twitter.com/{$value['screen_name']}\" title=\"{$value['name']}\">{$value['screen_name']}</a>";
break;
case 'urls':
$url = empty($value['expanded_url']) ? $value['url'] : $value['expanded_url'];
$display = isset($value['display_url']) ? $value['display_url'] : str_replace('http://', '', $url);
// Not all pages are served in UTF-8 so you may need to do this ...
$display = urldecode(str_replace('%E2%80%A6', '&hellip;', urlencode($display)));
$href = "<a href=\"{$value['url']}\">{$display}</a>";
break;
}
$keys[$value['indices']['0']] = substr(
$tweet['text'],
$value['indices']['0'],
$value['indices']['1'] - $value['indices']['0']
);
$replacements[$value['indices']['0']] = $href;
}
}
ksort($replacements);
$replacements = array_reverse($replacements, true);
$entified_tweet = $tweet['text'];
foreach ($replacements as $k => $v) {
$entified_tweet = substr_replace($entified_tweet, $v, $k, strlen($keys[$k]));
}
return $entified_tweet;
}
}
?>

@ -1,130 +0,0 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR .
dirname(__FILE__) . "/include");
require_once "functions.php";
require_once "sessions.php";
require_once "sanity_check.php";
require_once "config.php";
require_once "db.php";
//require_once "lib/twitteroauth/twitteroauth.php";
require_once "lib/tmhoauth/tmhOAuth.php";
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!init_connection($link)) return;
login_sequence($link);
$owner_uid = $_SESSION["uid"];
$op = $_REQUEST['op'];
if (!SINGLE_USER_MODE && !$_SESSION['uid']) {
render_login_form($link);
exit;
}
$callback_url = get_self_url_prefix() . "/twitter.php?op=callback";
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => CONSUMER_KEY,
'consumer_secret' => CONSUMER_SECRET,
));
if ($op == 'clear') {
unset($_SESSION['oauth']);
header("Location: twitter.php");
return;
}
if (isset($_REQUEST['oauth_verifier'])) {
$op = 'callback';
$tmhOAuth->config['user_token'] = $_SESSION['oauth']['oauth_token'];
$tmhOAuth->config['user_secret'] = $_SESSION['oauth']['oauth_token_secret'];
$code = $tmhOAuth->request('POST', $tmhOAuth->url('oauth/access_token', ''), array(
'oauth_verifier' => $_REQUEST['oauth_verifier']));
if ($code == 200) {
$access_token = json_encode($tmhOAuth->extract_params($tmhOAuth->response['response']));
unset($_SESSION['oauth']);
db_query($link, "UPDATE ttrss_users SET twitter_oauth = '$access_token'
WHERE id = ".$_SESSION['uid']);
} else {
header('Location: twitter.php?op=clear');
return;
}
}
if ($op == 'register') {
$code = $tmhOAuth->request('POST',
$tmhOAuth->url('oauth/request_token', ''), array(
'oauth_callback' => $callback));
if ($code == 200) {
$_SESSION['oauth'] = $tmhOAuth->extract_params($tmhOAuth->response['response']);
$method = isset($_REQUEST['signin']) ? 'authenticate' : 'authorize';
$force = isset($_REQUEST['force']) ? '&force_login=1' : '';
$forcewrite = isset($_REQUEST['force_write']) ? '&oauth_access_type=write' : '';
$forceread = isset($_REQUEST['force_read']) ? '&oauth_access_type=read' : '';
$location = $tmhOAuth->url("oauth/{$method}", '') .
"?oauth_token={$_SESSION['oauth']['oauth_token']}{$force}{$forcewrite}{$forceread}";
header("Location: $location");
}
}
?>
<html>
<head>
<title>Register with Twitter</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="utility.css">
</head>
<body>
<h1><?php echo __('Register with Twitter') ?></h1>
<?php if ($op == 'register') { ?>
<p><?php print_error(__('Could not connect to Twitter. Refresh the page or try again later.')) ?></p>
<?php } else if ($op == 'callback') { ?>
<p><?php print_notice(__('Congratulations! You have successfully registered with Twitter.')) ?>
</p>
<form method="GET" action="prefs.php">
<input type="hidden" name="tab" value="feedConfig">
<button type="submit"><?php echo __('Return to Tiny Tiny RSS') ?></button>
</form>
<?php } else { ?>
<form method="GET" action="twitter.php" style='display : inline'>
<input type="hidden" name="op" value="register">
<button type="submit"><?php echo __('Register') ?></button>
</form>
<form method="GET" action="prefs.php" style='display : inline'>
<input type="hidden" name="tab" value="feedConfig">
<button type="submit"><?php echo __('Return to Tiny Tiny RSS') ?></button>
</form>
<?php } ?>
</body>
</html>
Loading…
Cancel
Save