Asana API Adding an Attachment via cURL/PHP - asana

Experiencing difficulty trying to successfully add an attachment to a task using cURL/PHP.
$data = array("file" => "#$filename");
$headers = array("Authorization: Basic " . base64_encode($asana_api_key) . ":"));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://app.asana.com/api/1.0/tasks/$task_id/attachments");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_exec($ch);
Assume $filename, $asana_api_key, and $task_id are set properly. Should be fairly straightforward... but for some unknown reason I get the following response:
{"errors":[{"message":"Server Error","phrase":"19 snobby warthogs cheer busily"}]}
Oddly enough, running this request using curl command line works perfectly. I've tinkered with this for hours now to no avail.
Any ideas as to what the issue may be?

This was a bug on our end, and should now be fixed. It had to do with the way curl was sending the filename, namely, as the entire path to the file. Browsers typically send only the basename (without the directory). We now apply the same logic ourselves if we get a full path for our local name, and it seems like it works, but your case may be different.
I'd certainly appreciate knowing if it works for you now.

Related

Twilio API: Can't download the jpeg file in an MMS

I've built an SMS/MMS Lightning Component in Salesforce that uses Twilio. (You don't need to know anything about Salesforce to answer this question.) I'm able to display incoming MMS images using the MediaUrl provided. For that, I just put the MediaUrl in the img tag in the markup. From there, if I right-click the image, I can save to my computer, and it defaults to the filename used when the file was sent.
Now, I want to add a button to save the image to Salesforce Files (ContentVersion object). To do that, I'm making an HTTP GET call, expecting to get back the data in mime-type image/jpeg -- but instead, I'm getting back this XML response:
<TwilioResponse>
<Media>
<Sid/>
<AccountSid>[myAccountSid]</AccountSid>
<ParentSid/>
<ContentType/>
<DateCreated>Tue, 20 Nov 2018 01:11:04 +0000</DateCreated>
<DateUpdated>Tue, 20 Nov 201801:11:04 +0000</DateUpdated>
<Uri>/2010-04-01/Accounts/[myAccountSid]/Messages/MM96803e1b66cf37deb1bcf044799dbf8c/Media/ME46739a78eb197409a4a031896a22cab7</Uri>
</Media>
</TwilioResponse>
The Twilio docs here say you can get the media in the original mime-type by not including the .xml or .json extension on the URL. I'm not including an extension, and I'm even specifying the image/jpeg mime-type in the header. But still, I get the xml.
So, I can't get the actual media, just xml (or json) data about the media. I saw another thread saying I need to use the Uri to access the data -- but the Uri returned is exactly the same URL I'm calling originally -- the MediaUrl provided when the MMS is received.
Second issue is... how can I get that original file name. The browser knows the file name (it appears by default if I right-click and select Save As...), but I can't see any way to access it through the Twilio API.
This happens when the client you are using doesn't follow all the redirects for a URL of a media object. I was using PHP with file_get_contents() on a PHP 7.3 server and it wasn't following all of the redirects like I would have expected it to. I was getting the XML only like you described. I switched to using Guzzle and everything worked great using this code:
$client = new \GuzzleHttp\Client();
$client->get(
$url,
[
'save_to' => 'test.jpg',
]);
The way I found this was using a library that I was more familiar with that allowed me to disable redirects and I got the same response I was getting with PHPs file_get_contents(). Once I found that I could always get the XML if redirects were disabled, it was much easier to make progress.
I couldn't ever get file_get_contents to work with Twilio media URLs and gave up trying. Even specifying follow_location with file_get_contents() did not work (even though this should be the default) I tried this code, setting follow_location as well as other header values when trying to figure this out DID NOT WORK:
$opts = [
"http" => [
"follow_location" => '1',
"header" => "User-Agent: my-awesome-bot/1.0.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close",
],
];
$context = stream_context_create($opts);
$media = file_put_contents('test.jpg', file_get_contents($url, false, $context));
# got XML for media object only, not the raw image data in test.jpg
As far as the original filename, I don't think that information is available from Twilio. It is possible that it isn't stored with the uploaded file as everything is referenced by the object, parent and/or account SIDs in all the APIs I've seen and the corresponding documentation.
Twilio's MMS urls redirect to an Amazon AWS url. So you have to first use curl to get what the Amazon URL is. Then you can fetch the contents of that amazon URL.
//set the url you're getting from twilio
$twilioUrl=$_POST['MediaUrl0'];
//use some curl to get where that url redirects to
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $twilioURL);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$a = curl_exec($ch);
//here's that amazon url
$amazonURL = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
//and now you can do stuff to it like get its contents
$contents=file_get_contents($amazonURL);

Google email settings api error 403 with php curl

I am trying to update a signature through the Google email settings api. The domain is an EDU account, the user in question is a super admin. After successfully retrieving an OAuth 2.0 token, i issue this php curl code:
$mydomain = '<mydomain.com>';
$myuser = '<myusername>';
$token = '<mytoken>';
$url = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/'.$mydomain.'/'.$myuser.'/signature'
$data = '<?xml version="1.0" encoding="utf-8"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:apps="http://schemas.google.com/apps/2006">
<apps:property name="signature" value="blabla" />
</atom:entry>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/atom+xml', 'Authorization: Bearer '.$token));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
curl_close ($ch);
Which results in:
You are not authorized to access this API. Error 403
Because of other issues mentioned here about the client_id when getting authorized, i have tried the above with both the gserviceaccount.com address and the googleusercontent.com address, with the same results.
What am i doing wrong here?
To answer my own question: after speaking to a Google rep i have learned that the email settings api cannot be used through standard "web app" authorization but needs to be used through a "service account":
https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Best RoR approach for CURLing

I have the following piece of code in PHP. I'm looking for the best way to convert it to Ruby. I've looked at a few approaches, including open-uri and the curb and wrapper curb-fu libraries. open-uri doesn't look very good, but I really like the curb-fu approach. But, I have a feeling using two libraries for this is overkill, there has to be a simpler way to accomplish what this piece of code is doing.
#Setup connection
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $resource_uri);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_USERPWD, $site_public_key . ":" . $site_private_key);
curl_setopt($curl, CURLOPT_TIMEOUT, 15);
curl_setopt($curl, CURLOPT_VERBOSE, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl, CURLOPT_FAILONERROR, 0);
#Send request
$result_json = curl_exec($curl)
Your best bet is to use rest-client. Its api is really cool and lightweight :
result = RestClient::Request.new({:user => "username", :password => "password",
:method => :get, :url => "www.whatever.com"}).execute
or if you don't need auth you can simply do :
result = RestClient.get("http://www.whatever.com")

Accessing Clickbank API through Delphi's TIdHTTP?

I am trying to access the ClickBank API from my Delphi project, to check if a customer has a valid subscription.
I found the API Documentation here, but there are no Delphi examples. So I am trying to create my own little example, however I just cant figure it out with Indy's TIdHTTP.
Could anyone point me in the right direction, perhaps set up a minimal example?
P.S: I tried looking at the C# sample, however I cant port it to Delphi.
ClickBank sample C# is found here https://sandbox.clickbank.com/api_12_examples/api_example.csharp
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create("https://api.clickbank.com/rest/1.2/orders/list");
request.Accept = "application/xml";
request.Headers.Add(HttpRequestHeader.Authorization,
"<< DEVELOPER KEY >>:<< API KEY >>");
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
The PHP version is
https://sandbox.clickbank.com/api_12_examples/api_example.php
You'll see that they aren't doing much setup here... just setting two headers and performing a GET.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.clickbank.com/rest/1.2/orders/list");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_GET, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Accept: application/xml",
"Authorization: << DEVELOPER KEY >>:<< API KEY >>"));
$result = curl_exec($ch);
curl_close($ch);
In Delphi - a quick demo is to drop a TIdHTTP1 client on a form, along with a Button and a Memo. Then on an onclick of the button (where xxx= your developer key and yyy= your api key) do the same - set two headers and perform a GET:
IdHTTP1.Request.Accept := 'application/xml';
IdHTTP1.Request.CustomHeaders.Add('Authorization: xxx:yyy');
Memo1.Text := IdHTTP1.Get('https://api.clickbank.com/rest/1.2/orders/list');

Posting from a UTF-8 site to a ISO-8859-1 site (PHP)

Concerning the following situation:
www.foo.com is a page delivered in UTF-8. It features a login form to www.bar.com/Servlet. www.bar.com is a ISO-8859-1 capable application.
I have the following problem:
whenever someone is using special chars like German umlauts for his password the login fails because the password is posted in UTF-8, but the application expects it to be in ISO-8859-1.
Of course I could add accept-charset="ISO-8859-1" attribute to the html-form, but this (of course) does not work in IE.
I now thought of a proxy script, that is converting the UTF8 to ISO-8859-1 and posting that data to www.bar.com/Servlet. The conversion does work, also the posting (done by CURL). But as I'm echoing the returned html of www.bar.com/Servlet directly (and there is still www.foo.com in the address bar) the relative links in the html don't work. I managed to add a base tag to the output with an ugly replacement and it seems to work, but it's not a very elegant solution.
Is there a more simple way to post UTF-8-data to a ISO-8859-1 application?
My CURL code looks like this:
define('POSTURL', 'https://www.bar.com/Servlet');
array_map('utf8_decode', $_POST);
$ch = curl_init(POSTURL);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
$response = curl_exec($ch);
curl_close ($ch);
$response = preg_replace('/(<head(.*)>)/U', "$1<base href=\"https://www.bar.com\" />", $response);
echo $response;
exit;
I did not find a simple working solution. My solution is now to move the UTF-8-form that gets posted into an iframe on the same page and setting the charset to ISO-8859-1 within this iframe. The iframe-form posts to target="_top" then.

Resources