EzDevInfo.com

tumblr

Command line interface and Ruby client for the Tumblr API (v2)

HTML, Is there a color code for Transparent?

I'm building a new website, and I'm looking for a transparant navigation bar so the background is visible. Is there a way to change this?


Source: (StackOverflow)

{PreviousPost} and {NextPost} not working on Tumblr

It seems like {PreviousPost} and {NextPost} is not working on Tumblr for creating custom themes. Here's my code. Can someone point to my mistake...

<div>
    {block:PreviousPost}<a rel='nofollow' href="{PreviousPost}"><span>Previous Post</span></a>{/block:PreviousPost}
    {block:NextPost}<a rel='nofollow' href="{NextPost}"><span>Next Post</span></a>{/block:NextPost}
</div> 

Source: (StackOverflow)

Advertisements

Uploading Images to tumblr API from Android

One assumed using the Tumblr API to upload images would be easy. It isn't. (EDIT It is now, see Edit 2 at the end of this entry)

My app is supposed to upload an image to tumblr. I would prefer doing that from a service but for now I use an activity that closes itself as soon as its done uploading. In OnCreate() the user is authenticated:

consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);

// It uses this signature by default
// consumer.setMessageSigner(new HmacSha1MessageSigner());

provider = new CommonsHttpOAuthProvider(REQUEST_TOKEN_URL,ACCESS_TOKEN_URL,AUTH_URL);

String authUrl;
try 
{
authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL);
Log.d(TAG, "Auth url:" + authUrl);

startActivity(new Intent("android.intent.action.VIEW", Uri.parse(authUrl)));

} 

This opens a browser activity where the user can add username and passoword and then the app returns to the activity (this is also why I have to use an activity, I don't know how to do this from a service)

Returning from the browser the data is extracted

Uri uri = context.getIntent().getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) 
{  
    Log.d(TAG, "uri!=null");
    String verifier = uri.getQueryParameter("oauth_verifier");  
    Log.d(TAG, "verifier"+verifier);
    try 
    {
        provider.setOAuth10a(true);
        provider.retrieveAccessToken(consumer, verifier);
        Log.d(TAG, "try");
    } 
    catch (Exception e) 
    {
        Log.e(TAG, e.toString());
        e.printStackTrace();
    } 
OAUTH_TOKEN = consumer.getToken();
OAUTH_SECRET = consumer.getTokenSecret();

Most of these two snippets I got from here and they work well.

With these tokens I can now try putting data on tumblr. When I try to add Text this works fine using this method:

private void createText()
{
    if(!OAUTH_TOKEN.equals(""))
    {

        HttpContext context = new BasicHttpContext();
        HttpPost request = new HttpPost("http://api.tumblr.com/v2/blog/" + blogname + ".tumblr.com/post");

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("type", "text")); 
        nameValuePairs.add(new BasicNameValuePair("body", "this is just a test"));  

        try 
        {
        request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        } 
        catch (UnsupportedEncodingException e1) 
        {
            Log.e(TAG, e1.toString());
            e1.printStackTrace();
        }

        if (consumer == null)
        {
            consumer = new CommonsHttpOAuthConsumer(OAuthConstants.TUMBR_CONSUMERKEY, OAuthConstants.TUMBR_SECRETKEY);
        }
        if (OAUTH_TOKEN == null || OAUTH_SECRET == null)
        {
            Log.e(TAG, "Not logged in error");
        }
        consumer.setTokenWithSecret(OAUTH_TOKEN, OAUTH_SECRET);

        try 
        {
            consumer.sign(request);
        } 
        catch (OAuthMessageSignerException e) 
        {

        } 
        catch (OAuthExpectationFailedException e) 
        {
        } 
        catch (OAuthCommunicationException e) 
        {
        }
        HttpClient client = new DefaultHttpClient();
        //finally execute this request
        try 
        {
            HttpResponse response = client.execute(request, context);
            HttpEntity responseEntity = response.getEntity(); 
            if (responseEntity != null) 
            { 
                Log.d(TAG, "responseEntety!=null");
                try 
                {
                    Log.d(TAG, EntityUtils.toString(responseEntity));
                } 
                catch (ParseException e) 
                {
                    e.printStackTrace();
                    Log.e(TAG, e.toString());
                } 
                catch (IOException e) 
                {
                    e.printStackTrace();
                    Log.e(TAG, e.toString());
                } // gives me {"meta":{"status":401,"msg":"Not Authorized"},"response":[]} when I try to upload a photo
            }
            else
            {
                Log.d(TAG, "responseEntety==null");
            }
        } 
        catch (ClientProtocolException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    PostToTumblr.this.finish();
}

As you can see here http://www.tumblr.com/blog/snapnowandroid (at least as of this time) the text "this is just a test" is posted.

However, when I try to post images, it gets strange. Now I have checked around and apparently this is a well known issue with the tumblr API, which has excessively been discussed here and some have solved it in other programming languages (for example here) but I have been unable to repeat those successes.

The method (in its entirety bellow) has the exact same structure to the above method (that works), the nameValuePairs are just different

The method is given a Bitmap variable called photo

    private void uploadToTumblr(Bitmap photo)

This bitmap is converted into an array

ByteArrayOutputStream stream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bytes = stream.toByteArray();

The nameValuePairs are filled as follows

nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("type", enc), URLEncoder.encode("photo", enc)));
nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("caption", enc), URLEncoder.encode(text, enc))); 
nameValuePairs.add(new BasicNameValuePair("data", Base64.encodeToString(bytes, Base64.URL_SAFE))); 

The result is a {"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Error uploading photo."]}} from the tumblr api.

I have tries encoding the picture differently as discribed in this article but without any changes.

//http://www.coderanch.com/t/526487/java/java/Java-Byte-Hex-String
final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] hexChars = new char[bytes.length * 3];
int v;
for ( int j = 0; j < bytes.length; j++ ) 
{
    v = bytes[j] & 0xFF;
    hexChars[j * 3] = '%';
    hexChars[j * 3 + 1] = hexArray[v >>> 4];
    hexChars[j * 3 + 2] = hexArray[v & 0x0F];
}
String s = new String(hexChars);                
s = URLEncoder.encode(s, enc);
nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("data", enc), s)); 

Here the entire method (without the hex encoding):

private void uploadToTumblr(Bitmap photo)
{
    if(!OAUTH_TOKEN.equals(""))
    {

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] bytes = stream.toByteArray();

        String text ="SNAP";


        HttpContext context = new BasicHttpContext();
        HttpPost request = new HttpPost("http://api.tumblr.com/v2/blog/" + blogname + ".tumblr.com/post");

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); 
        String enc = "UTF-8"; 

        try 
        {
            nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("type", enc), URLEncoder.encode("photo", enc)));
            nameValuePairs.add(new BasicNameValuePair(URLEncoder.encode("caption", enc), URLEncoder.encode(text, enc))); 
            nameValuePairs.add(new BasicNameValuePair("data", Base64.encodeToString(bytes, Base64.URL_SAFE))); 
        } 
        catch (UnsupportedEncodingException e2) 
        {
            Log.e(TAG, e2.toString());
            e2.printStackTrace();
        } 
        try 
        {
            request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        } 
        catch (UnsupportedEncodingException e1) 
        {
            Log.e(TAG, e1.toString());
            e1.printStackTrace();
        }

        if (consumer == null)
        {
            consumer = new CommonsHttpOAuthConsumer(OAuthConstants.TUMBR_CONSUMERKEY, OAuthConstants.TUMBR_SECRETKEY);
        }
        if (OAUTH_TOKEN == null || OAUTH_SECRET == null)
        {
            //throw new LoginErrorException(LoginErrorException.NOT_LOGGED_IN);
            Log.e(TAG, "Not logged in error");
        }
        consumer.setTokenWithSecret(OAUTH_TOKEN, OAUTH_SECRET);

            try 
            {
                consumer.sign(request);
            } 
            catch (OAuthMessageSignerException e) 
            {

            } 
            catch (OAuthExpectationFailedException e) 
            {

            } 
            catch (OAuthCommunicationException e) 
            {
            }

            HttpClient client = new DefaultHttpClient();

            //finally execute this request
            try 
            {
                HttpResponse response = client.execute(request, context);
                HttpEntity responseEntity = response.getEntity(); 
                if (responseEntity != null) 
                { 
                    Log.d(TAG, "responseEntety!=null");
                    try 
                    {
                        Log.d(TAG, EntityUtils.toString(responseEntity));
                    } 
                    catch (ParseException e) 
                    {
                        e.printStackTrace();
                        Log.e(TAG, e.toString());
                    } 
                    catch (IOException e) 
                    {
                        e.printStackTrace();
                        Log.e(TAG, e.toString());
                    } 
                }
                else
                {
                    Log.d(TAG, "responseEntety==null");
                }
            } 
            catch (ClientProtocolException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


    }

    else
    {
        Log.d(TAG, "upload imposble... Toklen not set");
    }
    PostToTumblr.this.finish();
}

Now, while there are several things I am unhappy with (for example that this is done using an activity instead of a service) the big issue here is clearly the problem of uploading images. I am by no means the first to have this problem, so has anyone been able to get this done in java?

Edit 1

Have not made any progress with the problem at hand but created a workaround that might be nice for people who have the same issue. Tumblr offers posting via mail and you can programm android to send emails in the background as shown here. This works very well but you need to ask users to provide their mail account data and the Tumblr-mail Adress to post.

Edit 2

Years have pased and using email is no longer the easy way to do it. With jumblr there is finally a good API for Java that will work on android. OAuth-Authentication is no fun (it never is) but once you get past this, its fantastic.

Now, technically the question of how to do the authentication does not belong here but It's my overly long question, so I'll just paste some code here and if it's not interesting to you just skip it.

This uses a jar called jumblr-0.0.10-jar-with-dependencies.jar

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;

import com.tumblr.jumblr.JumblrClient;
import com.tumblr.jumblr.request.RequestBuilder;
import com.tumblr.jumblr.types.Blog;
import com.tumblr.jumblr.types.User;

import org.scribe.builder.ServiceBuilder;
import org.scribe.builder.api.TumblrApi;
import org.scribe.model.Token;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;

import java.io.File;


public class Tumblr
{
private static final String PROTECTED_RESOURCE_URL = "http://api.tumblr.com/v2/user/info";

static OAuthService service;
static Token requestToken=null;


public static void share(final Activity ctx, File file)
{
    Thread tt = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            JumblrClient client = new JumblrClient(Tumblr_Constants.CONSUMER_KEY, Tumblr_Constants.CONSUMER_SECRET);
            RequestBuilder requestBuilder = client.getRequestBuilder();
            requestBuilder.setConsumer(Tumblr_Constants.CONSUMER_KEY, Tumblr_Constants.CONSUMER_SECRET);
            SharedPreferences settings = ctx.getSharedPreferences("TumblrData", 0);
            String oauthToken=settings.getString("OauthToken", "");
            String oauthTokenSecret=settings.getString("OauthSecret", "");
            if(oauthToken.equals("") || oauthTokenSecret.equals(""))
            {
                authenticate(ctx);
                while(WebViewFragment.verifier.equals(""))
                {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String v = WebViewFragment.verifier;
                Token accessToken = authenticatefurther(v);
                SharedPreferences.Editor edit = settings.edit();
                edit.putString("OauthToken", accessToken.getToken());
                edit.putString("OauthSecret", accessToken.getSecret());
                edit.commit();
                oauthToken=settings.getString("OauthToken", "");
                oauthTokenSecret=settings.getString("OauthSecret", "");
            }
            if(!oauthToken.equals("") && !oauthTokenSecret.equals(""))
            {
                client.setToken(oauthToken, oauthTokenSecret);

                User user = client.user();
                System.out.println(user.getName());

                for (Blog blog : user.getBlogs()) {
                    Log.d("TUMBLR", blog.getTitle());
                }
            }
        }

    });
    tt.start();

}

private static void authenticate(Context ctx) {
    service = new ServiceBuilder()
            .provider( TumblrApi.class )
            .apiKey(Tumblr_Constants.CONSUMER_KEY)
            .apiSecret(Tumblr_Constants.CONSUMER_SECRET)
            .callback("snapnao://snapnao.de/ok") // OOB forbidden. We need an url and the better is on the tumblr website !
            .build();


    Log.d("TUMBLR", "=== Tumblr's OAuth Workflow ===" );
    System.out.println();

    // Obtain the Request Token
    Log.d("TUMBLR", "Fetching the Request Token...");
    requestToken = service.getRequestToken();
    Log.d("TUMBLR", "Got the Request Token!");
    Log.d("TUMBLR", "");

    Log.d("TUMBLR", "Now go and authorize Scribe here:" );
    Log.d("TUMBLR", service.getAuthorizationUrl( requestToken ) );

    String url = service.getAuthorizationUrl(requestToken);


    Intent i = new Intent(ctx, WebViewFragment.class);
    i.putExtra("url", url);
    ctx.startActivity(i);


}

private static Token authenticatefurther(String v)
{
    Token accessToken = null;
    Log.d("TUMBLR", "And paste the verifier here");
    Log.d("TUMBLR", ">>");

    Verifier verifier = new Verifier( v);
    Log.d("TUMBLR", "");

    // Trade the Request Token and Verfier for the Access Token
    Log.d("TUMBLR", "Trading the Request Token for an Access Token...");
    accessToken = service.getAccessToken( requestToken ,
            verifier );
    Log.d("TUMBLR", "Got the Access Token!");
    Log.d("TUMBLR", "(if your curious it looks like this: " + accessToken + " )");

    Log.d("TUMBLR", "");

    return accessToken;
}


}

The WebViewFragement looks like this

import android.app.Activity;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Bundle;
import android.util.Log;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebViewClient;


public class WebViewFragment extends Activity 
{
public static String verifier="";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.webviewfragment);

    String url = getIntent().getStringExtra("url");
    Log.d("TUMBLR", "webview-> "+url);
    WebView view = (WebView) findViewById(R.id.webView);
    view.setWebViewClient(
            new SSLTolerentWebViewClient()
    );
    view.getSettings().setJavaScriptEnabled(true);
    view.loadUrl(url);
}

// SSL Error Tolerant Web View Client
private class SSLTolerentWebViewClient extends WebViewClient {

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed(); // Ignore SSL certificate errors
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        Log.d("TUMBLR", "+++++"+url);
        if(url.contains("oauth_verifier="))
        {
            String[] x = url.split("oauth_verifier=");
            verifier=x[1].replace("#_=_", "");
            WebViewFragment.this.finish();
        }
    }
}
}

Source: (StackOverflow)

How can I load the content of tumblr nextPage on indexPage

I'm developing a tumblr theme for my personal portfolio, but I'm encountering a serious problem in my work section, I want to create an horizontal slider effect, when I click next to see older posts,

like this:

http://tympanus.net/Tutorials/WebsiteScrolling/

I have this to define my nextPage, #section4 is where I have the posts of my work:

<!-- Next Page -->
{block:NextPage}
<div>
    <a id="next-button" rel='nofollow' href="{NextPage}#section4" class="next panel" style="position:relative; top:630px; left:1550px;">next</a>
</div>
{/block:NextPage}
<!-- / Next Page -->

Well, this is defined to open an other page:

"indexPage".tumblr.com#section4

when I click next it goes to:

"indexPage".tumblr.com/page/2#section4

Is there a way I can do this slide effect on my index page or at least give the illusion, that I'm making slide effect, when moving to other page?


Source: (StackOverflow)

Anyone know what tumblr is written in

Does anyone know what tumblr is written in? I have been trying to figure it out.


Source: (StackOverflow)

What is the URL schema of Tumblr images?

What is the schema of a image-file at Tumblr? (I don't mean HTTP) I've only figured out that the domain of the servers where images are stored is <n>.media.tumblr.com, where n is a number between 1 and 31 and the name of the image file is prefixed with "tumblr_.

I'm asking because I want to find URLs that refer to the same image.

EDIT: I'm also processing URLs from other sources, not only Tumblr.


Source: (StackOverflow)

How do I get large images in my tumblr custom theme?

In Tumblr, the maximum image size is 500px. I want to know how to get larger images in my custom theme.


Source: (StackOverflow)

Tumblr API call or request limits

Anybody know if there is any API call limits per second, hour or day for Tumblr API? It seems to me the limits do exist when I make a lot of api calls in a short period via OAuth. However, I couldn't find any document on Tumblr API website or on Google. Many thanks.


Source: (StackOverflow)

jQuery - parsing JSON data - Having trouble with variable name

My first delve into working with JSON data. I have a bit of experience using jQuery though.

I'm posting to this URL (tumblr api): jyoseph.com/api/read/json

What I'm trying to do is output the json that gets returned. What I have so far:

$(document).ready(function(){ 

$.getJSON("http://jyoseph.com/api/read/json?callback=?", 
  function(data) { 
    //console.log(data); 
    console.log(data.posts);         

      $.each(data.posts, function(i,posts){ 
        var id = this.id; 
        var type = this.type; 
        var date = this.date; 
        var url = this.url; 
        var photo500 = this.photo-url-500; 

        $('ul').append('<li> ' +id+ ' - ' +type+ ' - ' +date+ ' - ' +url+ ' - ' +photo500+ ' - ' + ' </li>'); 
      }); 

  }); 

});

See my jsbin post for the entire script: http://jsbin.com/utaju/edit

Some of the keys from tumblr have "-" hyphens in them, and that seem to be causing a problem. As you can see "photo-url-500" or another "photo-caption" is causing the script to break, it's outputting NaN.

Is there a problem with having hyphens in the key names? Or am I going about this all wrong?


Source: (StackOverflow)

Customise Tumblr's *new* Like Button iFrame {LikeButton}

The new code from tumblr {LikeButton} comes with a very few options: color and size.

It injects an iFrame, which handles the "Like" functionality and provides SVG graphics.

However because of the iframe and cross site scripting policies, it is no longer possible to alter it with css nor to edit its contents.

How can I modify, or insert new code, to use my own Like button sprites or svgs?


Source: (StackOverflow)

Tumblr development tools

I want to create Tumblr theme and ineteresting is there any IDE (Netbeans, Eclipse, PHPStorm) plugins or tools for development? Ideal is to preview my theme in browser without uploading it to Tumblr. Thanks.


Source: (StackOverflow)

Tumblr sharer url override

Tumblr has a sharer just like facebook and twitter, tumblr's is: http://www.tumblr.com/share/. I believe that Tumblr's works by looking at the referring url and uses that.

I cannot seem to find any documentation to override that. I want to pass in an additional key into the url that is sent by default. Any idea's how to do this?

Thanks!


Source: (StackOverflow)

What is the "Default callback URL:" for Tumblr API v2?

Hi I am trying to use Tumblr API v2 and OAuth http://www.tumblr.com/docs/en/api/v2

First I have to register an application here: http://www.tumblr.com/oauth/apps

But what is the "Default callback URL"? Some random URL?

I just want to write to a Python program to make some posts using command line.

Thanks a lot!


Source: (StackOverflow)

Coldfusion Tumblr oAuth Frustration

I realize this is nothing new and that there are LOTS of posts on this topic already. However, non are exactly related to what I'm looking for... SO, here it goes:

I have reviewed EVERY other post on this topic and nothing seems to work for me. Here is a quick summary of what I am doing:

***I have been at this so long that I am losing track of where I am- I just realized that my oauth_signature is now missing from my authorization header. I know it was there before...

BTW- I am using a CF oauth app from Harry Klein (http://oauth.riaforge.org/):

<!--- set up the parameters --->
<cfset sConsumerKey = 'xxx'> <!--- Got these from Tumblr for my app --->
<cfset sConsumerSecret = 'xxx'> <!--- Got these from Tumblr for my app --->     
<cfset OAUTH_VERIFIER = 'xxx' /> <!--- Got these when doing oauth registration with tumblr for account --->
<cfset token = 'xxx' /> <!--- Got these when doing oauth registration with tumblr for account --->
<cfset tokenSecret = 'xxx' /> <!--- Got these when doing oauth registration with tumblr for account --->

<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").init(sKey = token, sSecret = tokenSecret)>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>

<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "GET",
    sHttpURL = 'http://api.tumblr.com/v2/user/info')> <!--- For now, just trying to get the user info --->
    <!--- The ultimate goal is to post to differnent blog accounts on tumblr --->

<cfset oReq.setParameter('oauth_verifier',oauth_verifier) /> <!--- Had to manually add in oauth_verifier if it is even needed --->

<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)> <!--- Sign the request --->

<cfhttp url="#oReq.GETNORMALIZEDHTTPURL()#" method="get">
    <cfhttpparam type="header" name="authorization" value="#oReq.TOHEADER()#" />
</cfhttp>

<cfdump var="#cfhttp#" />

Here is some of what I have gotten back (I have added line breaks to make it more legible):

SIGNATUREBASESTRING:
    GET&
    http%3A%2F%2Fapi.tumblr.com%2Fv2%2Fuser%2Finfo&
    oauth_consumer_key%3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%26
    oauth_nonce%3D96A76129198ADF9B60874521D3FB718256B2D093%26
    oauth_timestamp%3D1358463090%26
    oauth_token%3Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%26
    oauth_verifier%3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%26
    oauth_version%3D1.0 

AUTHORIZATION HEADER:
    OAuth oauth_consumer_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    oauth_timestamp="1358463090",
    oauth_version="1.0",
    oauth_nonce="96A76129198ADF9B60874521D3FB718256B2D093",
    oauth_token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    oauth_verifier="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 

Every time I try to modify anything, it never works. I always get 401 Not Authorized response from Tumblr with no explanation as to what I am doing wrong.

I've been at this for days: please help

*Edit 1/24/2013**

    1. Getting the access_token:
    response from Tumblr to auth_token request (Success):
    oauth_token=XXX&
    oauth_token_secret=XXX&
    oauth_callback_confirmed=true

    2. Using access token to get user info:
    sConsumerKey:
    xxx

    sConsumerSecret:
    yyy

    EndPoint:
    http://api.tumblr.com/v2/user/info

    COMMETHOD:
    get

    token:
    XXX

    tokenSecret:
    XXX

    Signature base string:
    GET&
    http%3A%2F%2Fapi.tumblr.com%2Fv2%2Fuser%2Finfo&
    oauth_consumer_key%3Dxxx&
    oauth_nonce%3DDED2857752C210C71D81DFD549B7B13113DCA50F&
    oauth_signature_method%3DHMAC-SHA1&
    oauth_timestamp%3D1358993908&
    oauth_token%XXX&
    oauth_version%3D1.0

    Signature:
    emffJ8+2QvExJzRH0fgDM8l3jDQ=

    Authorization Header:
    OAuth oauth_consumer_key="xxx"&
    oauth_nonce="DED2857752C210C71D81DFD549B7B13113DCA50F"&
    oauth_signature="emffJ8%2B2QvExJzRH0fgDM8l3jDQ%3D"&
    oauth_signature_method="HMAC-SHA1"&
    oauth_timestamp="1358993908"&
    oauth_token="XXX"&
    oauth_version="1.0" 

Verified that: 1. OAuth_token is correct. 2. oAuth Header is sorted in alphabetical order. 3. Signature base string contains no parameters because there are none. 4. Method is get. 5. OAuth Header contains oauth_signature.

Some questions are: 1. Are there any other headers that I need to include (not sure if CF is adding any in automatically) 2. Can anyone verify my signature base string? 3. Are there case sensitivity issues in the signature base string? (or anywhere else)

EDIT- 1/27/2013 Can anyone please confirm this info (I am using real values because everything will be reset after including the app itself):

Given:
1. Signature Base String:

GET&
http%3A%2F%2Fapi.tumblr.com%2Fv2%2Fuser%2Finfo&
oauth_consumer_key%XXX%26
oauth_nonce%3DOAUTH7DC9F837D60483B9D10389C9BB0AEAF9%26
oauth_signature_method%3DHMAC-SHA1%26
oauth_timestamp%3D1359320053%26
oauth_token%XXX%26
oauth_version%3D1.0

2. Signing Key (consumer secret & auth_token_secret):
XXX&
XXX

Is this signature correct?

3. Signature:
2n+xbj9gbOrADeaQ3nORKNhOTUg=    

Is this Authorization Header correct:

4. Authorization header (FYI- there is a space after each comma- is that ok?
And- is the encoding on the Signature ok?):
(Also, I've tried this in alphabetical order and not- same result)

OAuth oauth_signature="2n%2Bxbj9gbOrADeaQ3nORKNhOTUg%3D", 
oauth_token="XXX", 
oauth_consumer_key="XXX", 
oauth_nonce="OAUTH7DC9F837D60483B9D10389C9BB0AEAF9", 
oauth_signature_method="HMAC-SHA1", 
oauth_timestamp="1359320053", 
oauth_version="1.0"

I'm hoping someone can confirm that this is correct or not. In the latter case, I'll tweak it a little and hopefully check again. Thanks in advance all.


Source: (StackOverflow)

Need to post an image to Tumblr blog in android

I need to post a image to Tumblr. I read this http://www.tumblr.com/docs/en/api/v2#auth and I come to know I need to get the user info in order to get the blog name. I used the same code I used for Twitter authetication, changed the URLs and get successfully loaded the Tumblr webview. I used the following code to authenticate and to obtain the users info.

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.twitter.imageupload.R;
import com.twitter.imageupload.SecondClass;
import com.twitter.imageupload.TwitterImageUpload;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
import oauth.signpost.http.HttpParameters;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.http.AccessToken;
import twitter4j.http.OAuthAuthorization;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Window;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;


public class Tumblr_Web_View extends Activity {
    SharedPreferences settings;
    public static final String PREFS_NAME = "GREATEST_THINGS";
    SharedPreferences.Editor editor;
    final String TAG = getClass().getName();
    Button cancel_button;
    public static String usr_img, log_res, log_id;
    private OAuthConsumer consumer;
    private OAuthProvider provider;

    WebView tumblr_web_view;

    String tweet_Sign_in;
    static twitter4j.Twitter twitter;
    public static String userName;
    public static URL twt_img_url;
    AccessToken accessToken;
    SharedPreferences twtuname_pref;

    SharedPreferences userpref;
    public static final String USER_PREF = "TWITTER_USER";
    SharedPreferences.Editor usereditor;

    SharedPreferences twtlogpref;
    public static SharedPreferences.Editor twtlogeditor;
    public static final String TWTPREF_LOGIN = "LOGIN ID";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.tumblr_web_view);
        if (android.os.Build.VERSION.SDK_INT > 9) {

            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                    .permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        tumblr_web_view = (WebView) findViewById(R.id.tumblr_web_view);
        twtuname_pref = this.getSharedPreferences("user_pref", 1);
        settings = getSharedPreferences(PREFS_NAME, 0);
        editor = settings.edit();
        userpref = getSharedPreferences(USER_PREF, 0);
        twtlogpref = getSharedPreferences(TWTPREF_LOGIN, 0);
        try {
            this.consumer = new CommonsHttpOAuthConsumer(
                    Constants.CONSUMER_KEY, Constants.CONSUMER_SECRET);
            this.provider = new CommonsHttpOAuthProvider(Constants.REQUEST_URL,
                    Constants.ACCESS_URL, Constants.AUTHORIZE_URL);
        } catch (Exception e) {
            Log.e(TAG, "Error creating consumer / provider", e);
        }

        Log.i(TAG, "Starting task to retrieve request token.");
        // new OAuthRequestTokenTask(this,consumer,provider).execute();
        try {
            Log.i(TAG, "Retrieving request token from Google servers");
            final String url = provider.retrieveRequestToken(consumer,
                    Constants.OAUTH_CALLBACK_URL);
            Log.i(TAG, "Popping a browser with the authorize URL : " + url);
            // Intent intent = new Intent(Intent.ACTION_VIEW,
            // Uri.parse(url)).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP |
            // Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_FROM_BACKGROUND);
            // this.startActivity(intent);
            tumblr_web_view.loadUrl(url);

        } catch (Exception e) {
            Log.e(TAG, "Error during OAUth retrieve request token", e);
        }
    }

    /**
     * Called when the OAuthRequestTokenTask finishes (user has authorized the
     * request token). The callback URL will be intercepted here.
     */
    @Override
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        final Uri uri = intent.getData();
        if (uri != null
                && uri.getScheme().equals(Constants.OAUTH_CALLBACK_SCHEME)) {
            Log.i(TAG, "Callback received : " + uri);
            Log.i(TAG, "Retrieving Access Token");

            new RetrieveAccessTokenTask(this, consumer, provider, prefs)
                    .execute(uri);

            // finish();

        }
    }

    public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {

        @SuppressWarnings("unused")
        private Context context;
        private OAuthProvider provider;
        private OAuthConsumer consumer;
        private SharedPreferences prefs;

        public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,
                OAuthProvider provider, SharedPreferences prefs) {
            this.context = context;
            this.consumer = consumer;
            this.provider = provider;
            this.prefs = prefs;
        }

        /**
         * Retrieve the oauth_verifier, and store the oauth and
         * oauth_token_secret for future API calls.
         */
        @Override
        protected Void doInBackground(Uri... params) {
            Uri uri = params[0];
            Log.v("uri >>", uri + "");

            String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

            try {
                consumer.setTokenWithSecret(consumer.getToken(),
                        consumer.getTokenSecret());
            //  provider.retrieveAccessToken(consumer, oauth_verifier);

                Log.v("getToken", consumer.getToken());
                Log.v("getTokenSecret", consumer.getTokenSecret());

                Editor uname_editor = twtuname_pref.edit();
                uname_editor.putString("token", consumer.getToken());

                uname_editor.putString("secret_token",
                        consumer.getTokenSecret());
                uname_editor.putString("login_status", "already_logged");
                uname_editor.commit();

                HttpClient httpClient = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(
                        "http://api.tumblr.com/v2/user/info");
                try {

                    HttpResponse httpResponse = httpClient.execute(httpGet);
                    System.out.println("httpResponse");
                    InputStream inputStream = httpResponse.getEntity()
                            .getContent();
                    InputStreamReader inputStreamReader = new InputStreamReader(
                            inputStream);
                    BufferedReader bufferedReader = new BufferedReader(
                            inputStreamReader);
                    StringBuilder stringBuilder = new StringBuilder();
                    String bufferedStrChunk = null;
                    while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
                        stringBuilder.append(bufferedStrChunk);
                    }
                    System.out.println("Returning value of doInBackground :"
                            + stringBuilder.toString());
                } catch (ClientProtocolException cpe) {
                    System.out
                            .println("Exception generates caz of httpResponse :"
                                    + cpe);
                    cpe.printStackTrace();
                } catch (IOException ioe) {
                    System.out
                            .println("Second exception generates caz of httpResponse :"
                                    + ioe);
                    ioe.printStackTrace();
                }

            } catch (Exception e) {
                Log.e(TAG, "OAuth - Access Token Retrieval Error", e);
            }

            return null;
        }

    }

}

I got the following error.

 06-06 23:06:20.084: I/System.out(20264): Returning value of doInBackground :{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}

what I have done wrong?

update: Successfully got the user info now. Got the users blog name.

public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Void> {

            @SuppressWarnings("unused")
            private Context context;
            private OAuthProvider provider;
            private OAuthConsumer consumer;
            private SharedPreferences prefs;

            public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,
                    OAuthProvider provider, SharedPreferences prefs) {
                this.context = context;
                this.consumer = consumer;
                this.provider = provider;
                this.prefs = prefs;
            }

            /**
             * Retrieve the oauth_verifier, and store the oauth and
             * oauth_token_secret for future API calls.
             */
            @Override
            protected Void doInBackground(Uri... params) {
                Uri uri = params[0];
                Log.v("uri >>", uri + "");

                String oauth_verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

                try {
                    consumer.setTokenWithSecret(consumer.getToken(),
                            consumer.getTokenSecret());
                    provider.retrieveAccessToken(consumer, oauth_verifier);

                    Log.v("getToken", consumer.getToken());
                    Log.v("getTokenSecret", consumer.getTokenSecret());

                    Editor uname_editor = twtuname_pref.edit();
                    uname_editor.putString("token", consumer.getToken());

                    uname_editor.putString("secret_token",
                            consumer.getTokenSecret());
                    uname_editor.putString("login_status", "already_logged");
                    uname_editor.commit();

                    HttpClient httpClient = new DefaultHttpClient();
                    HttpGet httpGet = new HttpGet(
                            "http://api.tumblr.com/v2/user/info");
                    try {
        consumer.sign(httpGet);
                        HttpResponse httpResponse = httpClient.execute(httpGet);
                        System.out.println("httpResponse");
                        InputStream inputStream = httpResponse.getEntity()
                                .getContent();
                        InputStreamReader inputStreamReader = new InputStreamReader(
                                inputStream);
                        BufferedReader bufferedReader = new BufferedReader(
                                inputStreamReader);
                        StringBuilder stringBuilder = new StringBuilder();
                        String bufferedStrChunk = null;
                        while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
                            stringBuilder.append(bufferedStrChunk);
                        }
                        System.out.println("Returning value of doInBackground :"
                                + stringBuilder.toString());
                    } catch (ClientProtocolException cpe) {
                        System.out
                                .println("Exception generates caz of httpResponse :"
                                        + cpe);
                        cpe.printStackTrace();
                    } catch (IOException ioe) {
                        System.out
                                .println("Second exception generates caz of httpResponse :"
                                        + ioe);
                        ioe.printStackTrace();
                    }

                } catch (Exception e) {
                    Log.e(TAG, "OAuth - Access Token Retrieval Error", e);
                }

                return null;
            }

        }

I tried to post a image to the logged in user's blog. Used the following code. But didn't get the response.

try {
                                HttpClient client = new DefaultHttpClient();
                                client.getConnectionManager()
                                        .getSchemeRegistry()
                                        .register(
                                                new Scheme("SSLSocketFactory", SSLSocketFactory
                                                        .getSocketFactory(), 443));
                                HttpConnectionParams.setConnectionTimeout(client.getParams(),
                                        10000);
                                HttpResponse response1;
                                HttpPost post = new HttpPost(
                                        "http://api.tumblr.com/v2/blog/"+username+".tumblr.com/post");
                                consumer.sign(post);
                                JSONObject json_obj_val = new JSONObject();
                                json_obj_val.put("type", "photo");
                                json_obj_val.put("caption", "test");
                                json_obj_val.put("source", "http://50.57.227.117/blacksheep/uploaded/Detailed_images/961314275649aladdins.jpg");

                                    post.setHeader("Content-Type", "application/json");
                                post.setHeader("Accept", "application/json");
                                StringEntity entity_val = new StringEntity(
                                        json_obj_val.toString());
                                entity_val.setContentEncoding(new BasicHeader(
                                        HTTP.CONTENT_TYPE, "application/json"));
                                post.setEntity(entity_val);
                                response1 = client.execute(post);
                                String response_string = EntityUtils.toString(response1.getEntity());
                                Log.v("response >>", response_string);
                                Log.v("response length >>", response_string.length() + "");
                            } catch (UnsupportedEncodingException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (ClientProtocolException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (ParseException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (JSONException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (IOException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (OAuthMessageSignerException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (OAuthExpectationFailedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (OAuthCommunicationException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

Got the following response. what is wrong in the code?

06-11 16:24:46.312: V/response >>(27710): {"meta":{"status":400,"msg":"Bad Request"},"response":{"errors":["Post cannot be empty."]}}

Source: (StackOverflow)