here is my php code
<?php
class twitter
{
public $consumer_key;
public $consumer_secret;
public $access_token;
public $access_token_secret;
public $http_code;
public $http_info;
public $host = 'https://api.twitter.com/1.1/';
public $postdata;
public $timeout = 30;
public $connecttimeout = 30;
public $ssl_verifypeer = FALSE;
public $format = 'json';
public $decode_json = TRUE;
public $useragent = 'Mars Bot';
public $debug = FALSE;
public static $version = '1.0';
public static $SignatureMethod = 'HMAC-SHA1';
public static $boundary = '';
private $parameters;
private $http_method;
private $http_url;
private $http_header;
private $proxyinuse = FALSE;
private $proxyandport;
private $userandpass;
public function init($consumer_key, $consumer_secret, $access_token, $access_token_secret, $proxyinuse = FALSE, $proxyandport = '', $userandpass = '', $debug = false){
$this->consumer_key = $consumer_key;
$this->consumer_secret = $consumer_secret;
$this->access_token = $access_token;
$this->access_token_secret = $access_token_secret;
$this->proxyinuse = $proxyinuse;
$this->proxyandport = $proxyandport;
$this->userandpass = $userandpass;
$this->debug = $debug;
}
private static function generate_nonce(){
$mt = microtime();
$rand = mt_rand();
return md5($mt . $rand);
}
private static function generate_timestamp(){
return time();
}
public function get_normalized_http_url(){
$parts = parse_url($this->http_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";
}
return "$scheme://$host$path";
}
public function get_normalized_http_method(){
return strtoupper($this->http_method);
}
public function get_signature_base_string() {
$parts = array(
$this->get_normalized_http_method(),
$this->get_normalized_http_url(),
$this->get_signable_parameters()
);
$parts = self::urlencode_rfc3986($parts);
return implode('&', $parts);
}
public function get_signable_parameters()
{
$params = $this->parameters;
if(isset($params['media[]'])){
unset($params['media[]']);
}
if (isset($params['oauth_signature'])){
unset($params['oauth_signature']);
}
return self::build_http_query($params);
}
public static function urlencode_rfc3986($input){
if(is_array($input)){
return array_map(array('self', 'urlencode_rfc3986'), $input);
}elseif(is_scalar($input)){
return str_replace('+', ' ', str_replace('%7E', '~', rawurlencode($input)));
}else{
return '';
}
}
public function set_parameter($name, $value, $allow_duplicates = true){
if ($allow_duplicates && isset($this->parameters[$name])){
if (is_scalar($this->parameters[$name])){
$this->parameters[$name] = array($this->parameters[$name]);
}
$this->parameters[$name][] = $value;
}else{
$this->parameters[$name] = $value;
}
}
public function set_base_data($http_method, $http_url, $parameters=NULL)
{
@$parameters or $parameters = array();
$defaults = array(
'oauth_version' => self::$version,
'oauth_token' => $this->access_token,
'oauth_timestamp' => self::generate_timestamp(),
'oauth_nonce' => self::generate_nonce(),
'oauth_consumer_key' => $this->consumer_key,
);
$parameters = array_merge($defaults, $parameters);
$this->parameters = $parameters;
$this->http_method = $http_method;
$this->http_url = $http_url;
}
public function build_signature()
{
$base_string = $this->get_signature_base_string();
$key_parts = array($this->consumer_secret, $this->access_token_secret);
$key_parts = self::urlencode_rfc3986($key_parts);
$key = implode('&', $key_parts);
return base64_encode(hash_hmac('sha1', $base_string, $key, true));
}
public function set_sign_request_data()
{
$this->set_parameter('oauth_signature_method', self::$SignatureMethod, false);
$signature = $this->build_signature();
$this->set_parameter('oauth_signature', $signature, false);
}
public function to_postdata( $multi = false ){
if($multi)
return self::build_http_query_multi($this->parameters);
else
return self::build_http_query($this->parameters);
}
public function to_header($realm=null) {
$first = true;
if($realm) {
$out = 'Authorization: OAuth realm="' . self::urlencode_rfc3986($realm) . '"';
$first = false;
} else
$out = 'Authorization: OAuth';
$total = array();
foreach ($this->parameters as $k => $v) {
if (substr($k, 0, 5) != "oauth") continue;
if (is_array($v)) {
throw new Exception('Arrays not supported in headers');
}
$out .= ($first) ? ' ' : ',';
$out .= self::urlencode_rfc3986($k) .
'="' .
self::urlencode_rfc3986($v) .
'"';
$first = false;
}
return $out;
}
public function to_url(){
$post_data = $this->to_postdata();
$out = $this->get_normalized_http_url();
if($post_data){
$out .= '?'.$post_data;
}
return $out;
}
public function oAuthRequest($url, $method, $parameters, $multi=false)
{
if (strrpos($url, 'http://') !== 0 && strrpos($url, 'http://') !== 0){
$url = "{$this->host}{$url}.{$this->format}";
}
$this->set_base_data($method, $url, $parameters);
$this->set_sign_request_data();
switch ($method){
case 'GET':
return $this->http($this->to_url(), 'GET');
default:
return $this->http($this->get_normalized_http_url(), $method, $this->to_postdata($multi));
}
}
function http($url, $method, $postfields=null, $multi=false, $headermulti = "")
{
$this->http_info = array();
$ci = curl_init();
curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
curl_setopt($ci, CURLOPT_HEADER, false);
if($this->proxyinuse){
if($this->proxyandport){
curl_setopt($ci, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ci, CURLOPT_PROXY, $this->proxyandport);
}
if($this->userandpass){
curl_setopt($ci, CURLOPT_PROXYUSERPWD, $this->userandpass);
}
}
switch ($method)
{
case 'POST':
curl_setopt($ci, CURLOPT_POST, true);
if (!empty($postfields))
{
curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
}
break;
case 'DELETE':
curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
if (!empty($postfields))
{
$url = "{$url}?{$postfields}";
}
default:
break;
}
$header_array=array();
if($multi)
$header_array = array("Content-Type: multipart/form-data; boundary=" . self::$boundary , "Expect: ");
array_push($header_array,$headermulti);
curl_setopt($ci, CURLOPT_HTTPHEADER, $header_array);
curl_setopt($ci, CURLINFO_HEADER_OUT, true);
curl_setopt($ci, CURLOPT_URL, $url);
$response = curl_exec($ci);
$this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
$this->http_info = array_merge($this->http_info, curl_getinfo($ci));
$this->url = $url;
if ($this->debug) {
echo "=====post data======\r\n";
var_dump($postfields);
echo '=====info====='."\r\n";
print_r( curl_getinfo($ci) );
echo '=====$response====='."\r\n";
print_r( $response );
}
curl_close ($ci);
return $response;
}
public static function build_http_query($params){
if (!$params) return '';
$keys = self::urlencode_rfc3986(array_keys($params));
$values = self::urlencode_rfc3986(array_values($params));
$params = array_combine($keys, $values);
uksort($params, 'strcmp');
$pairs = array();
foreach ($params as $parameter => $value){
if (is_array($value)){
natsort($value);
foreach ($value as $duplicate_value){
$pairs[] = $parameter . '=' . $duplicate_value;
}
}else{
$pairs[] = $parameter . '=' . $value;
}
}
return implode('&', $pairs);
}
public static function build_http_query_multi($params) {
if (!$params) return '';
uksort($params, 'strcmp');
$pairs = array();
self::$boundary = $boundary = uniqid('------------------');
$MPboundary = '--'.$boundary;
$endMPboundary = $MPboundary. '--';
$multipartbody = '';
foreach ($params as $parameter => $value) {
if( in_array($parameter, array('media[]')) && $value{0} == '@' ) {
$url = ltrim( $value, '@' );
$content = file_get_contents( $url );
$array = explode( '?', basename( $url ) );
$filename = $array[0];
$multipartbody .= $MPboundary . "\r\n";
$multipartbody .= 'Content-Disposition: form-data; name="' . $parameter . '"; filename="' . $filename . '"'. "\r\n";
$multipartbody .= 'Content-Type: application/octet-stream' ."\r\n\r\n";
$multipartbody .= $content. "\r\n";
} else {
$multipartbody .= $MPboundary . "\r\n";
$multipartbody .= 'content-disposition: form-data; name="' . $parameter . "\"\r\n\r\n";
$multipartbody .= $value."\r\n";
}
}
$multipartbody .= $endMPboundary;
return $multipartbody;
}
function getHeader($ch, $header){
$i = strpos($header, ':');
if (!empty($i))
{
$key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
$value = trim(substr($header, $i + 2));
$this->http_header[$key] = $value;
}
return strlen($header);
}
function post($url, $parameters=array(), $multi = false){
$response = $this->oAuthRequest($url, 'POST', $parameters , $multi);
if ($this->format === 'json' && $this->decode_json)
{
return json_decode($response, true);
}
return $response;
}
function add($text)
{
$param = array();
$param['status'] = $text;
return $this->post('statuses/update', $param);
}
public function addpic($status, $pic_path, $lat = NULL, $long = NULL)
{
$params = array();
$params['status'] = $status;
$params['media[]'] = '@'.$pic_path;
if ($lat) {
$params['lat'] = floatval($lat);
}
if ($long) {
$params['long'] = floatval($long);
}
return $this->post('statuses/update_with_media', $params, true);
}
}
$c = new twitter();
$c->init($consumer_key, $consumer_secret, $access_token, $access_token_secret, $proxyinuse, $proxyandport, $userandpass);
$c->addpic('xxxxx', 'E:\\1.jpg');
btw, $c-add('xxxxx') works well