JavaScript: Cookies aren't cleared on logout from user page - javascript

I'm using cookies to keep the user's information present on the front end. Logging them in is happening through Passport.
On login, the code sets the cookies from the user's information returned from Passport.
On logout, the cookies are unset and then /auth/logout is called to log the user.
Everything works with login/logout, but whenever I try to delete the cookies on logout, nothing happens.
This only occurs on the user.js page of my site. I am able to successfully log off from any other page
Here's my code:
Dynamically Setting the navbar
document.getElementById( 'navigation-bar' ).innerHTML =
'<ul>'+
"<li><button onclick='Home();' id='home-link'>Home</button></li>"+
"<li><a id='recipes-link' href='/recipes'>Recipes</a></li>"+
"<li><a id='festivals-link' href='/festivals'>Festivals</a></li>"+
"<li><button id='logout-button' onclick='Logout()'>Logout</button></li>"+
'</ul>';
Logout Function
function Logout() {
//Sets each cookie's expire time to 1970, forcing expire.
DeleteCookies();
//Runs Passport's 'logout' function
window.open( '/auth/logout', '_parent' );
}
Setting The Cookies
function Login () {
//Setting user parameters.
let login = { email: null, password: null };
login.email = document.getElementById( 'email' ).value;
login.password = document.getElementById( 'password' ).value;
PostRequest( '/auth/login', login, 'application/json', ( status, data ) => {
if ( status == 200 ) {
//Set 'expireTime' to current date and then add 1 hour to it.
let expireTime = new Date( Date.now() );
expireTime.setHours( expireTime.getHours() + 1 );
// Parse the return data.
let user = JSON.parse(data);
//Set cookie for each user key.
for ( const key in user ) {
document.cookie = key + '=' + user[key] + ';expires=' + expireTime.toUTCString() + ";";
}
//Open user's profile in another window using name as url.
window.open( '/user/' + user.username, '_parent' );
} else {
console.log('error');
}
});
}
Deleting The Cookies
function DeleteCookies() {
console.log( 'this is running' );
//Use old date to expire the cookies
let expire = 'expires=Thu, 01 Jan 1970 00:00:00 GMT;'
//Split each cookie into an array element.
let cookiesArray = document.cookie.split(";");
//Split the cookie to have name as the first value.
//Then use the cookie's name to expire the cookie.
for ( let cookie = 0; cookie < cookiesArray.length; cookie++ ) {
let name = cookiesArray[cookie].split( "=" )[0];
document.cookie = name + "=;" + expire;
}
}
Checking If Cookie Is Set
function IsLoggedIn() {
//If user is logged in, display the logout button.
if ( GetCookie( '_id' ) != '' ) {
document.getElementById( 'logout-button' ).style.display = 'inline-block';
}
}
user.js code
var user = {};
function UserReady() {
GetRequest( '/api/me', undefined, ( status, data ) => {
if ( status === 200 ) {
user = JSON.parse( data );
document.getElementById( 'username' ).innerHTML = "Welcome back, " + user.username;
}
});
}
All help is appreciated.

Related

Download with post to hide username and password?

I have the code below. I want to use Post() instead of Get() because I don't want to show the username and password in the string. First I get auth and download a cookie with post(). This works fine. But then I download a xml-file with get() and the username and password is visible in the download string. How can I download latest.xml with post()? I don't get any file at all (latest.xml) if I change to post whre I have the comment (Does not work if I change to Post()).
The url is https and not http.
var apiUrl = s.getPropertyValue('apiUrl');
var apiUser = s.getPropertyValue('apiUser');
var apiPass = s.getPropertyValue('apiPass');
var anyOrders = "";
var theHTTP = new HTTP();
theHTTP.resetParameters();
theHTTP.url = apiUrl + "/wsauth?";
theHTTP.addParameter("username", apiUser);
theHTTP.addParameter("password", apiPass);
theHTTP.authScheme = HTTP.BasicAuth;
theHTTP.post(); //Works fine
while( !theHTTP.waitForFinished( 1 ) ) { }
job.log(-1, "Server response: " + theHTTP.getServerResponse().toString("UTF-8"));
if( theHTTP.finishedStatus != HTTP.Ok )
{
job.fail("The request failed: %1", theHTTP.lastError);
return;
}
var theCookie = theHTTP.getHeaderValue( HTTP.SetCookie ).toString( "UTF-8" );
if( theCookie.isEmpty() )
{
job.fail("Invalid cookie response: %1", theHTTP.lastError);
return;
}
s.log(-1, "Cookie: " + theCookie);
//Perform query to get xml file
theHTTP.addHeader( HTTP.Cookie, theCookie );
theHTTP.url = apiUrl + "/order/latest";
theHTTP.localFilePath = job.createPathWithName("latest.xml", false);
job.log(1,theHTTP.localFilePath, false);
theHTTP.get(); //Does not work if I change to Post()
job.log( 4, "Download started", 100 );
while( !theHTTP.waitForFinished( 3 ) ) {
job.log( 5, "Downloading...", theHTTP.progress() );
}
job.log( 6, "Download finished" );
//open file to read if there are any orders
var f = new File(theHTTP.localFilePath);
f.open(File.ReadOnly);
anyOrders = f.read();
f.close();
if( theHTTP.finishedStatus == HTTP.Ok && File.exists(theHTTP.localFilePath)) {
if(anyOrders == "No non-processed order found!") {
job.sendToNull( job.getPath() );
job.log( 1, "No non-processed order found! File deleted!");
} else {
job.log( 1, "Download completed successfully");
job.sendToSingle(theHTTP.localFilePath);
}
}
else {
job.fail("Download failed with the status code %1", theHTTP.statusCode);
job.sendToNull( job.getPath() );
return;
}

AJAX without jQuery is not sending POST data to PHP file

I've been trying to get an ajax alert layer to work with a POST method for several days and I can't come up with a reason for it not working. I use the same basic code to send form data through ajax with POST on other admin pages without trouble but when I try to send data that does not come from a form nothing gets to the server in $_POST.
Here's the flow of the code...
I use variables on a page like these:
$alertLayer = 1;
$autoCloseAlertLayer = 1;
$addAlertLayerCloseButton = 1;
$alertLayerMessage = $alertLayerMessage . '<h1>Test</h1><p>3rd test of the alert layer module.</p>';
$redirect = 0;
$redirectTo = 0;
and I include a script that calls a function at the bottom of the page like this:
if ($alertLayer == true)
{
echo "<script type='text/javascript' id='alertLayerScript'>Lib.ajaxAlertFunction('/Modules/AlertLayer', $autoCloseAlertLayer, $addAlertLayerCloseButton, '$alertLayerMessage', $redirect, '$redirectTo');</script>";
}
Here's the script that gets called:
Lib.ajaxAlertFunction = function (senturl, autoClose, closeButton, message, redirect, redirectTo)
{
var ajaxRequest;
try
{
ajaxRequest = new XMLHttpRequest();
}
catch (e)
{
try
{
ajaxRequest = new ActiveXObjext("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
ajaxRequest = new ActiveXObjext("Microsoft.XMLHTTP");
}
catch (e)
{
alert ("Your browser can't handle the truth!");
return false;
}
}
}
if (!senturl)
{
return false;
}
else
{
// var data = "autoClose=" + encodeURIComponent(autoClose) + "&closeButton=" + encodeURIComponent(closeButton) + "&message=" + encodeURIComponent(message) + "&redirect=" + encodeURIComponent(redirect) + "&redirectTo=" + encodeURIComponent(redirectTo);
// var data = encodeURIComponent("autoClose=" + autoClose + "&closeButton=" + closeButton + "&message=" + message + "&redirect=" + redirect + "&redirectTo=" + redirectTo);
var data = "autoClose=" + autoClose + "&closeButton=" + closeButton + "&message=" + message + "&redirect=" + redirect + "&redirectTo=" + redirectTo;
}
ajaxRequest.onreadystatechange = function()
{
if (ajaxRequest.readyState == 4 && ajaxRequest.status == 200)
{
document.getElementById('outerFrame').innerHTML += ajaxRequest.responseText;
newAlertLayer = document.getElementById('alertLayer');
var arr = newAlertLayer.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
{
eval(arr[n].innerHTML)
}
}
}
ajaxRequest.open('POST', senturl, true);
ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajaxRequest.send(data);
}
NOTE: I have no problem sending this data with a 'GET' method but then a long message gets cut off. I have also tried to set up the 'data' variable in several different methods that I've searched over the past 3 days with no success.
The code that expects $_POST data goes as follows:
<?php
$ROOT = $_SERVER['DOCUMENT_ROOT'];
?>
<div id="alertLayer">
<link rel="stylesheet" href="<?php $ROOT ?>/Modules/AlertLayer/alertLayer.css">
<script src="/Modules/AlertLayer/alertLayer.js"></script>
<div id="alertBlock">
<?php
foreach ($_POST as $key => $value)
{
echo "<p>" . $key . " = " . $value . "</p>";
}
foreach ($_GET as $key => $value)
{
echo "<p>" . $key . " = " . $value . "</p>";
}
?>
</div>
</div>
What am I missing? What is different from sending form data with POST and sending variables concatenated the same way?
Again, GET is working when I add the data to the url string but not sufficient, POST = no data at all received on the other end of the ajaxRequest but the rest of the request returns exactly what is expected. The $_POST data missing from the server request is currently the only problem that I cannot solve with this code.
It's looking like the request is not being sent properly but I'm unable to determine the reason. Here's a screenshot of what NETWORK tab in chrome:
Problem was a redirection (301) issued by nginx due to a missing slash at the end of the URL. This caused the POST request to be changed to GET.
Technical Details: https://softwareengineering.stackexchange.com/questions/99894/why-doesnt-http-have-post-redirect
Old approach that started the discussion:
Your Problem seems to be the encodeURIComponent() function that you're wrapping around the whole data string. This replaces the & signs with & values. If you debug this in the browsers developer console you'll see that it is not recognized as form data in the request. You should only escape the variables you're filling in.
Btw: This should also be problematic when you use GET.
This is more or less what I tried and it was sending data via POST.
window.onload=function(){
Lib.ajaxAlertFunction( '/test/target.php', 0, 0, 'Fantastic - data is being sent via POST! Amazeballs!', 0, 0 );
};
var Lib={}; /* Because I don't have the rest of `Lib` at my disposal */
Lib.ajaxAlertFunction = function ( senturl, autoClose, closeButton, message, redirect, redirectTo ) {
var ajax;/* renamed only for brevity */
try {
ajax = new XMLHttpRequest();
} catch (e) {
try {
ajax = new ActiveXObjext("Msxml2.XMLHTTP");
} catch (e) {
try {
ajax = new ActiveXObjext("Microsoft.XMLHTTP");
} catch (e) {
alert ("Your browser can't handle the truth!");
return false;
}
}
}
if ( !senturl ) return false;
else {
var data = "autoClose=" + autoClose + "&closeButton=" + closeButton + "&message=" + message + "&redirect=" + redirect + "&redirectTo=" + redirectTo;
}
ajax.onreadystatechange = function() {
if( ajax.readyState == 4 && ajax.status == 200 ) {
/*
document.getElementById('outerFrame').innerHTML += ajax.responseText;
newAlertLayer = document.getElementById('alertLayer');
var arr = newAlertLayer.getElementsByTagName('script')
for ( var n = 0; n < arr.length; n++ ) {
eval( arr[n].innerHTML );
}
*/
console.log( ajax.responseText );
}
}
ajax.open( 'POST', senturl, true );
ajax.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
ajax.send( data );
}
For the sake of the test, /test/target.php was simply:
<?php
exit( print_r($_POST,true) );
?>
and the response:
Array
(
[autoClose] => 0
[closeButton] => 0
[message] => Fantastic - data is being sent via POST! Amazeballs!
[redirect] => 0
[redirectTo] => 0
)
If it helps any, here is a basic ajax function I use in tests, perhaps something in there might be of use?
function _ajax( url, options ){
var factories=[
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
function() { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); },
function() { return new ActiveXObject('MSXML2.XMLHTTP.4.0'); },
function() { return new ActiveXObject('MSXML2.XMLHTTP.5.0'); },
function() { return new ActiveXObject('MSXML2.XMLHTTP.6.0'); },
function() { return new ActiveXObject('Microsoft.XMLHTTP'); }
];
/* Try each factory until we have a winner */
for( var i=0; i < factories.length; i++ ) {
try { var req = factories[ i ](); if( req!=null ) { break; } }
catch( err ) { continue; }
};
var method=options.hasOwnProperty('method') ? options.method.toUpperCase() : 'POST';
var callback=options.hasOwnProperty('callback') ? options.callback :false;
if( !callback ){
alert( 'No callback function assigned - a callback is required to handle the response data' );
return false;
}
var headers={
'Accept': "text/html, application/xml, application/json, text/javascript, "+"*"+"/"+"*"+"; charset=utf-8",
'Content-type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
};
/* The main parameters of the request */
var params=[];
if( options.hasOwnProperty('params') && typeof( options.params )=='object' ){
for( var n in options.params ) params.push( n + '=' + options.params[n] );
}
/* Additional arguments that can be passed to the callback function */
var args=options.hasOwnProperty('args') ? options.args : options;
/* Assign callback to handle response */
req.onreadystatechange=function(){
if( req.readyState==4 ) {
if( req.status==200 ) options.callback.call( this, req.response, args );
else console.warn( 'Error: '+req.status+' status code returned' );
}
}
/* Execute the request according to desired method */
switch( method ){
case 'POST':
req.open( method, url, true );
for( header in headers ) req.setRequestHeader( header, headers[ header ] );
req.send( params.join('&') );
break;
case 'GET':
req.open( method, url+'?'+params.join('&'), true );
for( header in headers ) req.setRequestHeader( header, headers[ header ] );
req.send( null );
break;
}
}
/* to use */
_ajax.call( this, '/test/target.php',{ callback:console.info, method:'post',params:{'field':'value','field2':'value2'} } );
When calling the ajaxRequest the url MUST have a "/" at the end of the url (if you're not specifying an /index.php file for example).
I was using '/Modules/AlertLayer' and changing to '/Modules/AlertLayer/' has fixed the problem!

Parse JS add user with role

I am trying to basically have a sign up form that will sign up a user and also add that user that just signed up to a certan role. I got the app signing up the user fine but it isnt creating the role and adding the user to that role. Here is what I had
<script type="text/javascript">
Parse.initialize("key", "key");
//set the user
var user = new Parse.User();
$( "form" ).submit(function( event ) {
//get the input data
var username = $('#username').val();
var email = $('#email').val();
var password = $('#password').val();
var facility = $('#facility').val();
//Set the user info
user.set("facility", "" + facility + "");
user.set("username", "" + username + "");
user.set("email", "" + email + "");
user.set("password", "" + password + "");
//Sign them up
user.signUp(null, {
success: function(user) {
// Hooray! Let them use the app now.
//Make the role
var roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
var role = new Parse.Role("Pro", roleACL);
role.getUsers().add(username);
role.save();
//Show and Hide the alert
$('#successModal').modal('show');
setTimeout(function(){
$('#successModal').modal('hide')
}, 4000);
//Clear the form
$( 'form' ).each(function(){
this.reset();
});
},
error: function(user, error) {
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});
return false
});
</script>
My thought was create the user then on successful user creation create the role and add the user to that role. Seems not to be working though.
code the querys a user
querys a role
then adds the user to the role
var qu = new Parse.Query(Parse.User);
var qr = new Parse.Query(Parse.Role);
qr.get(roleId, {
success: function(role) {
_role = role;
qu.get(userId, {
success: function(user) {
_role.getACL().setRoleReadAccess(_role, true);
_role.getUsers().add(user);
_role.save();
response.success(_role.toJSON());
},
error: function(object, error) {
console.log('got role, failed on get user');
}
});
The aim is to add the newly saved user to an existing role, so that role must be queried, not created when the user is saved.
Since you must the save of a user, query a role, and save that role -- three asynch operations that must be performed in sequence -- it's advisable to use promises, lest the code become unreadably indented, so...
// prepare the user as you have it, then
user.signUp().then(function(user) {
// query the role, you can get it with the role name
var roleQuery = new Parse.Query(Parse.Role);
roleQuery.equalTo("name", "Pro");
return roleQuery.first();
}).then(function(role) {
role.getUsers().add(user);
return role.save();
}).then(function() {
// no need to set a timer. with the promise, we know exactly when we are done
$('#successModal').modal('hide');
}, function(error) {
alert("Error: " + error.code + " " + error.message);
});
Be sure to first create the "Pro" role manually using the data browser. Read through the security section in the programming guide.
Also note, if this happens for every user, the role code is a good candidate to be part of an afterSave cloud function on PFUser.

How to post image on twitter in Phonegap using javascript

I'm currently implementing a web smartphone application with Phonegap. On this application, users can post images they take with the phone camera on Facebook. This feature has been succesfully implemented only using javascript, by sending a base 64 encoded image. Now, I want to implement the same feature using Twitter.
I found some very interesting blog posts about this and I'm already be able to update the user status only using javascript... but I can't post images too using the update_with_media Twitter web service.
According too this post, someone says it's impossible to implement this operation without using a server side code (like a php script for example).
So my question is : is it possible to use the update_with_media Twitter web service only with javascript ?
I send you my code to have an overview of the current solution. I've taken this article as working base : http://oodlestechnologies.com/blogs/Twitter-integration-on-PhoneGap-using-ChildBrowser-and-OAuth-for-iOS-and-Android-Platforms
Here is my HTML code.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script type="text/javascript" src="../js/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../cordova-2.5.0.js"></script>
<script type="text/javascript" src="../js/childBrowser/childbrowser.js"></script>
<script type="text/javascript" src="../js/helpers/jsOAuth-1.3.6.js"></script>
<script type="text/javascript" src="../js/helpers/twitter.js"></script>
</head>
<body>
<h4>Oodles Twitter App</h4>
<table border="1">
<tr>
<th>Login using Twitter</th>
<th>
<button id="loginBtn" onclick="Twitter.init();">Login</button>
<button id="logoutBtn" onclick="logOut();">Logout</button>
</th>
</tr>
<tr id="tweetText">
<td colspan="2"><textarea id="tweet"></textarea></td>
</tr>
<tr id="tweetBtn">
<td colspan="2" align="right">
<button id="tweeter" onclick="Twitter.tweet();">Tweet</button>
</td>
</tr>
<tr><td colspan="2"><div id="welcome">Please Login to use this app</div></td></tr>
</table>
<br/>
<br/>
<button onclick="javascript:location.reload();">Recharger la page</button>
</body>
</html>
Here is my twitter.js code : (The point is in the post method)
$(document).ready(function() {
document.addEventListener("deviceready", onDeviceReady, false);
});
function onDeviceReady() {
var root = this;
cb = window.plugins.childBrowser;
if (!localStorage.getItem(twitterKey)) {
$("#loginBtn").show();
$("#logoutBtn").hide();
$("tweetBtn").hide();
$("tweetText").hide();
}
else {
$("#loginBtn").hide();
$("#logoutBtn").show();
$("tweetBtn").show();
$("tweetText").show();
}
if (cb != null) {
cb.onLocationChange = function(loc) {
root.locChanged(loc);
};
cb.onClose = function() {
root.onCloseBrowser()
};
cb.onOpenExternal = function() {
root.onOpenExternal();
};
}
}
function onCloseBrowser() {
console.log("onCloseBrowser!");
}
function locChanged(loc) {
console.log("locChanged!");
}
function onOpenExternal() {
console.log("onOpenExternal!");
}
// Consumer key : ...
// Consumer secret : ...
// GLOBAL VARS
var oauth; // It Holds the oAuth data request
var requestParams; // Specific param related to request
var options = {consumerKey: '...', consumerSecret: '...', callbackUrl: "http://www.google.fr"};
var twitterKey = "twtrKey"; // This key is used for storing Information related
var Twitter = {
init: function() {
// Apps storedAccessData , Apps Data in Raw format
var storedAccessData, rawData = localStorage.getItem(twitterKey);
// here we are going to check whether the data about user is already with us.
if (localStorage.getItem(twitterKey) !== null) {
// when App already knows data
storedAccessData = JSON.parse(rawData); //JSON parsing
//options.accessTokenKey = storedAccessData.accessTokenKey; // data will be saved when user first time signin
options.accessTokenSecret = storedAccessData.accessTokenSecret; // data will be saved when user first first signin
// javascript OAuth take care of everything for app we need to provide just the options
oauth = OAuth(options);
oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
function(data) {
var entry = JSON.parse(data.text);
console.log("USERNAME: " + entry.screen_name);
}
);
}
else {
// we have no data for save user
oauth = OAuth(options);
oauth.get('https://api.twitter.com/oauth/request_token',
function(data) {
requestParams = data.text;
cb.showWebPage('https://api.twitter.com/oauth/authorize?' + data.text); // This opens the Twitter authorization / sign in page
cb.onLocationChange = function(loc) {
Twitter.success(loc);
}; // Here will will track the change in URL of ChildBrowser
},
function(data) {
console.log("ERROR: " + JSON.stringify(data));
}
);
}
},
/*
When ChildBrowser's URL changes we will track it here.
We will also be acknowledged was the request is a successful or unsuccessful
*/
success: function(loc) {
// Here the URL of supplied callback will Load
/*
Here Plugin will check whether the callback Url matches with the given Url
*/
if (loc.indexOf("http://www.google.fr") >= 0) {
// Parse the returned URL
var index, verifier = '';
var params = loc.substr(loc.indexOf('?') + 1);
params = params.split('&');
for (var i = 0; i < params.length; i++) {
var y = params[i].split('=');
if (y[0] === 'oauth_verifier') {
verifier = y[1];
}
}
// Here we are going to change token for request with token for access
/*
Once user has authorised us then we have to change the token for request with token of access
here we will give data to localStorage.
*/
oauth.get('https://api.twitter.com/oauth/access_token?oauth_verifier=' + verifier + '&' + requestParams,
function(data) {
var accessParams = {};
var qvars_tmp = data.text.split('&');
for (var i = 0; i < qvars_tmp.length; i++) {
var y = qvars_tmp[i].split('=');
accessParams[y[0]] = decodeURIComponent(y[1]);
}
$('#oauthStatus').html('<span style="color:green;">Success!</span>');
$('#stage-auth').hide();
$('#stage-data').show();
oauth.setAccessToken([accessParams.oauth_token, accessParams.oauth_token_secret]);
// Saving token of access in Local_Storage
var accessData = {};
accessData.accessTokenKey = accessParams.oauth_token;
accessData.accessTokenSecret = accessParams.oauth_token_secret;
// Configuring Apps LOCAL_STORAGE
console.log("TWITTER: Storing token key/secret in localStorage");
localStorage.setItem(twitterKey, JSON.stringify(accessData));
oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
function(data) {
var entry = JSON.parse(data.text);
console.log("TWITTER USER: " + entry.screen_name);
$("#welcome").show();
document.getElementById("welcome").innerHTML = "welcome " + entry.screen_name;
successfulLogin();
// Just for eg.
app.init();
},
function(data) {
console.log("ERROR: " + data);
}
);
// Now we have to close the child browser because everthing goes on track.
window.plugins.childBrowser.close();
},
function(data) {
console.log(data);
}
);
}
else {
// Just Empty
}
},
tweet: function() {
var storedAccessData, rawData = localStorage.getItem(twitterKey);
storedAccessData = JSON.parse(rawData); // Paring Json
options.accessTokenKey = storedAccessData.accessTokenKey; // it will be saved on first signin
options.accessTokenSecret = storedAccessData.accessTokenSecret; // it will be save on first login
// javascript OAuth will care of else for app we need to send only the options
oauth = OAuth(options);
oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true',
function(data) {
var entry = JSON.parse(data.text);
Twitter.post();
}
);
},
/*
We now have the data to tweet
*/
post: function() {
alert('Post !');
var theTweet = $("#tweet").val(); // You can change it with what else you likes.
oauth.post('https://upload.twitter.com/1/statuses/update_with_media.json',
{
'status': theTweet,
'media': //HERE IS THE PROBLEM, WHAT TO DO HERE ?
}, "multipart/form-data",
function(data)
{
alert('Data 1 !');
console.log('------Data1 : ' + data);
var entry = JSON.parse(data.text);
console.log(entry);
done();
},
function(data) {
//var json_result = JSON.parse(data);
//alert(json_result.text.error);
var entry = JSON.stringify(data);
console.log('------Data2 : ' + entry);
}
);
}
}
function done() {
alert("OKKK !");
$("#tweet").val('');
}
function successfulLogin() {
$("#loginBtn").hide();
$("#logoutBtn,#tweet,#tweeter,#tweetBtn,#tweetText").show();
}
function logOut() {
//localStorage.clear();
window.localStorage.removeItem(twitterKey);
document.getElementById("welcome").innerHTML = "Please Login to use this app";
$("#loginBtn").show();
$("#logoutBtn,#tweet,#tweeter,#tweetText,#tweetBtn").hide();
}
After many tests (sending a base64 image, sending a blob, sending a binary file, ...) here is the return message from Twitter I have :
{\"errors\":[{\"message\":\"Internal
error\",\"code\":131}]}","xml":"","requestHeaders":{"Content-Type":"multipart/form-data"},"responseHeaders":{"date":"Fri,
19 Apr 2013 15:45:28
GMT","content-encoding":"deflate","strict-transport-security":"max-age=631138519","status":"500
Internal Server
Error","server":"tfe","content-type":"application/json;
charset=utf-8","version":"HTTP/1.1"}}
A "solution" (by send a blob) have been posted on the Twitter dev forum but not working for me : dev.twitter.com/discussions/6969
Does anyone want to implement the same feature or have a solution ? Thank you !
------ EDITED :
I just want to use Javascript and I don't want to implement any server-side solution (no PHP, C#, Java...).
According to the docs, Twitter requires the multipart/form-data enctype, which means a base64 string isn't going to work.
Unlike POST statuses/update, this method expects raw multipart data. Your POST request's Content-Type should be set to multipart/form-data with the media[] parameter ~ https://dev.twitter.com/docs/api/1/post/statuses/update_with_media
However, you could host an endpoint that takes base64, converts it to a real file, and forwards the request to Twitter. For example (untested):
<?php
$base64 = $_POST['image'];
$data = base64_decode( $base64 );
// Make name unique to avoid conflicts.
$temp_file = uniqid() . $_POST['name'];
// Save the file to a temp location.
file_put_contents( $temp_file, $data );
$temp_info = pathinfo( $temp_file );
$temp_type = $temp_info['extension'];
$temp_name = basename( $temp_file, '.' . $temp_type );
// OAuth library recommended by Twitter: https://github.com/themattharris/tmhOAuth
// See original: https://github.com/themattharris/tmhOAuth-examples/blob/master/images.php
require 'tmhOAuth.php';
require 'tmhUtilities.php';
$tmhOAuth = new tmhOAuth( array(
'consumer_key' => $_POST['consumer_key'],
'consumer_secret' => $_POST['consumer_secret'],
'user_token' => $_POST['user_token'],
'user_secret' => $_POST['user_secret'],
));
// note the type and filename are set here as well
// Edit: Not sure if the `type` and `filename` params are necessary.
$params = array( 'media[]' => "#{$temp_file};type={$temp_type};filename={$temp_name}" );
$code = $tmhOAuth->request( 'POST', $tmhOAuth->url( '1/status/update_with_media' ),
$params,
true, // use auth
true // multipart
);
// Remove temp file.
unlink( $temp_file );
if ( $code == 200 ) {
tmhUtilities::pr( json_decode( $tmhOAuth->response['response'] ) );
}
tmhUtilities::pr( htmlentities( $tmhOAuth->response['response'] ) );
?>
And you might call it like:
$.ajax({
// You'll want to use https to protect the oauth info.
url: "https://mysite.com/proxy.php",
type: "POST",
data: {
image: "base64 data...",
name: "foo.png",
consumer_key: options.consumerKey,
consumer_secret: options.consumerSecret,
user_token: options.accessTokenKey,
user_secret: options.accessTokenSecret
},
success: function( data ) {
console.log( data );
}
});
For anyone trying to post images to Twitter using client JS, I was able to post to twitter using the solution by gary-buynary-co-za (https://github.com/bytespider/jsOAuth/pull/11) at the end of this forum. Pretty much ended up using Phonegap FileTransfer and FileTransferOptions objects for transferring image to twitter api, but used jsOAuth for preparing FileTransferOptions headers and signatures. The solution could definitely be cleaned up though.

Issues With Pop-Up Blocking (this shouldn't be happening?)

First to clarify, I am trying to open a pop-up in response to a user event.
I am developing an application on Facebook that involves e-commerce transactions, and for reasons related to my EV SSL certificates, I have to open our billing terminal in a new, fully-secure window. As such, the process goes as follows:
User selects "new card" as payment method and enter's the recipient's shipping address
User clicks "Place Order," which uses an AJAX call to validate the address, and IF valid, syncs it with the database.
IF address is valid (AJAX success: function()), and the user selected "new card," then the secure billing terminal is supposed to open using a window.open call.
As I understand it, most modern browsers including Chrome, Firefox, and Safari are supposed to traverse up the chain to determine if the source event was user-initiated (in this case, it was--a click event), however despite this I cannot seem to prevent this pop-up from getting blocked and my users are having a great deal of trouble figuring out what's going on.
Unfortunately Chrome doesn't make it all that noticeable when a pop-up is blocked, so most users will not notice this and will assume that the app is simply "broken."
Any ideas? We're a week from launch and I'm getting desperate...
[EDIT] Here is the code for reference:
/* -- Step 3: Complete Checkout Click -- */
$('div.finishGroupOrder').live('click', function() {
/* User is Click-Happy? */
if ( $('div#billing-contents div#loader').length ) {
alert('Your order is processing. We know it\'s hard, but please be patient.');
return false;
}
var paymentMethod = $('input[name="method"]:checked').val(); // Payment Method Selected ( Card on File / New / PayPal )
var secureSession = $(this).attr('secure'); // Secure Session ID
var orderData = { addressSelection: $('input[name="address"]:checked').val(),
price: $('div.price').attr('value') };
/* Form Validation */
switch( orderData.addressSelection ) {
case 'new': // User chose to enter address manually
var allInputs = $('div#new-address').find('input:not(#address2), select');
var validInputs = $('div#new-address').find('input[value!=""]:not(#address2), select[value!=""]');
if ( allInputs.length === validInputs.length ) { // All inputs are valid, capture their contents
allInputs.removeClass('bad-value');
var address = { phone: $('input#phone').val(),
address1: $('input#address1').val(),
address2: $('input#address2').val(),
city: $('input#city').val(),
state: $('select#state').val(),
zip: $('input#zipcode').val() };
var validatedAddress = validation.validateAddress(address);
if (validatedAddress) {
address.address1 = validatedAddress.address1;
address.address2 = validatedAddress.address2;
address.city = validatedAddress.city;
address.state = validatedAddress.state;
address.timeOffset = validatedAddress.timeOffset; // Time offset from EST (PST = -3, EST = 0, etc.)
$('input#timezone').val(address.timeOffset);
} else {
allInputs.addClass('bad-value');
return false;
}
} else { // Some inputs are invalid, prompt the user to fix them
allInputs.filter(function() { return ($.inArray( this, validInputs ) > -1) ? false : true; }).addClass('bad-value');
return false;
}
break;
case 'verified': // User chose to ship to verified address
var address = { address1: 'verified' };
break;
default:
alert('Please choose an address where you want the flowers to be delivered.');
return false;
break;
}
/* Sync Order With Updated Address Information */
$.ajax({ type: 'POST',
url: location.protocol + '//' + location.host + '/_ajax/order.ajax.php',
data: 'action=update_order&' + $.param( address ),
success: function() {
/* Load Selected Payment Method */
switch( paymentMethod ) {
//case 'paypal': paypal(); break;
case 'member':
newGroupOrderDialogActions.payAsMember();
break;
case 'newCard':
newGroupOrderDialogActions.payWithCard( secureSession );
//$('div.group-secure-terminal').trigger('click');
break;
}
}
});
And the newGroupOrderActions.payWithCard()...
/* -- Pay With a New Credit Card -- */
payWithCard: function( session ) {
var windowHeight = 769; // Terminal Height
var windowWidth = 638; // Terminal Width
var w = screen.availWidth; // Available Screen (W)
var h = screen.availHeight; // Available Screen (H)
var top = (h-windowHeight)/2; // Center Positioning
var left = (w-windowWidth)/2; // Center Positioning
/* Open Secure Order Terminal */
var secureTerminal = window.open('https://secure.mydomain.ly/contribute?id=' + session, 'myCompany: Secure Checkout', 'menubar=0,toolbar=0,location=1,resizable=0,scrollbars=1,height='+windowHeight+',width='+windowWidth+',top='+top+',left='+left);
/* Check for Secure Order Terminal Close Event */
var onFinish = setInterval(function() {
try {
if (secureTerminal.closed) { // Window has been unloaded, check the order to see if it has been approved
clearTimeout(onFinish);
$.ajax({ type: 'POST',
url: location.protocol + '//' + location.host + '/_ajax/redirect.ajax.php',
data: 'action=group_order_status_redirect',
success: function(redirect) { newGroupOrderDialogActions.publishOrder( redirect ) } // If redirect is not null, order was successful. Redirect to order page
});
}
} catch (e) {}
}, 200);
},

Categories