Wordpress nonce check always false - ajax

I'm having problems with a basic nonce validation via an ajax request.
Those are my script loader and css loader functions:
(in gallery.php)
function gallery_js_loader()
{
if (!is_admin()) return;
// async flash uploader
wp_enqueue_script('swfobject', THEMEURL . "/lib/uploadify/swfobject.js", array(), false, true);
wp_enqueue_script('uploadify', THEMEURL . "/lib/uploadify/jquery.uploadify.v2.1.4.min.js", array('jquery'), false, true);
wp_enqueue_script('gallery_admin_scripts', THEMEURL . "/inc/galleries/gallery_admin_scripts.js", array(), false, true);
wp_localize_script('gallery_admin_scripts', 'param',
array(
'basename' => GALLERYPOST,
'baselocation' => THEMEURL,
'nonce' => wp_create_nonce('file-upload-nonce'),
'thumb_width' => intval(get_option('thumbnail_size_w')),
'thumb_height' => intval(get_option('thumbnail_size_h'))
));
// main styles
}
function gallery_css_loader()
{
wp_enqueue_style('uploadify_styles', THEMEURL . "/lib/uploadify/uploadify.css");
wp_enqueue_style('gallery_admin_styles', THEMEURL . "/inc/galleries/gallery_admin_styles.css");
}
add_action('admin_print_scripts-post.php', 'gallery_js_loader');
add_action('admin_print_scripts-post-new.php', 'gallery_js_loader');
add_action('admin_print_styles-post.php', 'gallery_css_loader');
add_action('admin_print_styles-post-new.php', 'gallery_css_loader');
function gallery_upload_image()
{
$nonce = $_POST["nonce"];
if (is_admin() && !empty($_FILES) /*&& wp_verify_nonce($nonce, 'file-upload-nonce')*/) {
require_once(ABSPATH . 'wp-admin/includes/image.php');
$tempFile = $_FILES['Filedata']['tmp_name'];
// $targetPath = $_SERVER['DOCUMENT_ROOT'] . $_REQUEST['folder'] . '/';
$targetDir = wp_upload_dir(date('Y'));
$targetFile = $targetDir['path'] . '/' . $_FILES['Filedata']['name'];
$targetFile = str_replace(" ", "", $targetFile);
move_uploaded_file($tempFile, $targetFile);
$wp_filetype = wp_check_filetype(basename($targetFile), null);
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($targetFile)),
'post_content' => '',
'post_status' => 'inherit'
);
$result['attachmet_id'] = $attach_id = wp_insert_attachment($attachment, $targetFile);
$result['recieved_nonce'] = $nonce;
$attach_data = wp_generate_attachment_metadata($attach_id, $targetFile);
wp_update_attachment_metadata($attach_id, $attach_data);
$result['success'] = true;
} else {
$result['success'] = false;
$result['recieved_nounce'] = $nonce;
$result['error'] = array(
'message' => 'No files or you are not admin ' . $nonce,
'code' => 'E01'
);
}
echo json_encode($result);
exit;
}
add_action('wp_ajax_do_upload', 'gallery_upload_image');
In my javascrtip file:
(in gallery.js)
console.debug("Nonce received ",param.nonce); //c4817b947a
My ajax call will access a do_upload action from php. This one will append the received nonce field to the response...
(back in gallery.php)
function gallery_upload_image()
{
$nonce = $_POST["nonce"];
if ( wp_verify_nonce($nonce, 'file-upload-nonce')) {
/* some logic here, nothing to do with nonce */
$result['success'] = true;
$result['debugNonce'] = $nonce;
} // end validation
else {
//invalid nonce
$result['success'] = false;
$result['debugNonce'] = $nonce;
}
}
The received result looks like this:
c4817b947a {"success":false,"debugNonce":"c4817b947a"}
The first c4817b947a is because of the echo from the nonce generation function. It does not influence the way the validation happens.
My conclusion is that wp_verify_nonce always fails.
I am using wp 3.2.1 on localhost, fresh install, no plugins.

I've just ran into a similar issue and it turned out that all I had to do is to re-log as admin. I think it should also work in your case, because everything else in the provided code seems to be fine.
I guess it has something to do with how sessions are handled in Wordpress.

I do an almost identical interchange without problems.
This is in a plugin (class), but that shouldn't matter.
PHP - initialize the javascript :
add_action( 'wp_print_scripts', array( &$this, 'enqueue_script') );
PHP - function enqueue_script:
wp_localize_script( 'B99-Portfolio', 'ajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ),
'imgurl' => content_url().'/uploads/portfolio-content/',
'requestNonce' => wp_create_nonce('b99-request-nonce')) );
JS - initiate the ajax request:
$.ajax({
type : 'POST',
cache : false,
url : ajax.ajaxurl,
data : {
action : 'b99_ajax_request_items',
requestNonce : ajax.requestNonce
},
dataType: 'json',
error : function(jqXHR, textStatus, errorThrown) {alert(jqXHR+" "+textStatus+" "+errorThrown);},
success : function( response ) {recieveAjax( response );}
});
PHP - recieve and handle the request ( function b99_ajax_request_items):
$nonce = $_POST['requestNonce'];
if ( ! wp_verify_nonce( $nonce, 'b99-request-nonce' ) ){
die ( 'security fail'.$nonce);
}
Make sure that you have enqueued the script prior to localizing it.
I'm using current versions of both jquery and wordpress and this works seamlessly on a local install of XAMPP. It looks pretty similar to your interchange, but maybe this is something to compare against.

Related

How to set an ajax url in wordpress? I want to call it with datatables.net in server side processing mode

I want to set up an ajax url to use it with Datatables in wordpress. But I don't know how I would set up the corresponding url in wordpress. I guess its a rather easy task but don't know how to do it.
I found example code how to set up datatables server side processing in wordpress but I am struggling to put the following code in real life (how to create the corresponding FrontendConfig.ajaxurl in Wordpress? Or would it be better to create a wordpress json endpoint?)
jQuery
jQuery('#student_table').DataTable({
"bProcessing": true,
"serverSide": true,
"ajax":{
"url": FrontendConfig.ajaxurl+'?action=getStudentsFromExamIdAjax&exam_nounce=exam_nounce_data&exam_id=1',
type: "post",
}
});
Wordpress php
add_action('wp_ajax_getStudentsFromExamIdAjax', 'getStudentsFromExamIdAjax' );
add_action('wp_ajax_nopriv_getStudentsFromExamIdAjax', 'getStudentsFromExamIdAjax' );
function getStudentsFromExamIdAjax(){
if(empty($_GET['action']) || empty($_GET['exam_id'])){
wp_send_json_error( new \WP_Error( 'Bad Request' ) );
}
if(isset($_GET['exam_id']) && $_SERVER['REQUEST_METHOD'] === 'POST' && wp_verify_nonce( $_GET['exam_nounce'], 'exam_nounce_data' )):
$exam_id = (isset($_GET['exam_id'])) ? absint($_GET['exam_id']) : '';
/*# You can create a function to get the data here */
$students = getStudentsFromExamId($exam_id);
$tdata = [];
foreach ($students as $key => $value):
$tdata[$key][] = $value->roll_no;
$tdata[$key][] = $value->name;
$tdata[$key][] = $value->phone;
$tdata[$key][] = 'action here';
endforeach;
$total_records = count($tdata);
$json_data = array(
/* $_REQUEST['draw'] comes from the datatable, you can print to ensure that */
"draw" => intval( $_REQUEST['draw'] ),
"recordsTotal" => intval( $total_records ),
"recordsFiltered" => intval( $total_records ),
"data" => $tdata
);
echo json_encode($json_data);
endif;
wp_die();
}
You just need to set the following enqueue_style_and_scripts into your function.php file. You need to set wp_localize_script, check this link https://developer.wordpress.org/reference/functions/wp_localize_script/. Don't forget to change the code as per your coding requirement.
/*# Enqueue styles & scripts */
if( !function_exists('enqueue_style_and_scripts') ):
function enqueue_style_and_scripts(){
$version = wp_get_theme()->get('Version');
wp_enqueue_script(
'general_js',
get_stylesheet_directory_uri() . '/assets/js/general.js',
array('jquery'),
$version,
true
);
$frontendconfig = array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'is_user_logged_in' => is_user_logged_in(),
);
wp_localize_script( 'general_js', 'FrontendConfig', $frontendconfig );
}
add_action('wp_enqueue_scripts', 'enqueue_style_and_scripts');
endif;

Laravel send image from vue to controller

I'm trying to save an image when updating an item but I'm having trouble sending the file to the controller in order to save it. This is how I'm sending it
submit(item) {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$inertia.post('/courses/' + item.id, {
name: this.ruleForm.name,
summary: this.ruleForm.summary,
description: this.ruleForm.description,
price: this.ruleForm.price,
hours: this.ruleForm.hours,
min_grade: this.ruleForm.min_grade,
file: this.imagen,
matery: this.matery,
remover: this.remover,
strict: this.strict
}).then(
() => {
this.$message({
type: 'success',
message: 'Guardado correctamente.'
});
this.loading = false
},
(res) => {
this.$message.error(parseError(res)[0]);
this.loading = false;
})
} else {
return false;
}
});
},
If I {{imagen}} and {{imageUrl}} in the vue this is the result respectively, this is why I'm sending the imagen and not the url
[object File]
blob:http://dev.inae.com/9c77fa72-b778-45c9-8ab2-0a9084282415
When I Log::info($request) this is the output, when adding a file and changing text and saving,
local.INFO: array (
'name' => 'Principiante Clase 3 (automático)',
'summary' => 'Enseñaremos a compresionar el vehículo y la utilización de
cambios en vehículo automático',
'description' => '<p>Enseñaremos a compresionar el vehículo y la utilización de
cambios en vehículo automático (viaje a fraijanes).</p>',
'price' => 52000,
'hours' => 2,
'min_grade' => 70,
'file' =>
array (
'uid' => 1576507762527,
),
'matery' => NULL,
'remover' => false,
'strict' => false,
)
However if I only add the image and don't change anything else, nothing happens in the Log
Code for updating the image in the controller, in the update function
//Log is here
$editCourse = Course::find($id);
$destino = "img/courses";
$link = public_path();
if ($request->hasFile('file')) {
if (!empty($editCourse->image) && file_exists($link . $editCourse->image)) {
unlink($link . $editCourse->image);
}
$image = $request->file('file');
$imageName = Uuid::generate(4)->string . '.' . $image->getClientOriginalExtension();
$editCourse->image = '/' . $destino . '/' . $imageName;
$request->file('file')->move($destino, $imageName);
}
What could I be doing wrong?
You likely need to use the FormData object like so:
let data = new FormData();
data.append('file', this.imagen);
// Attach the other properties.
data.append(...);
$inertia.post(data);
This is because you shouldnt upload files using x-www-form-urlencoded, instead you should be using multipart/form-data which allows you to upload binary data. This also means that the backend will not receive a JSON string anymore, but a form-data response. Laravel should handle this automatically though.

HybridAuth send tweet with image

I'm using the HybridAuth library.
I'd like to be able to post message to my authenticated users twitter profile with images.
The setUserStatus method works well to automatically send a tweet.
I wrote the following method :
function setUserStatus( $status, $image )
{
//$parameters = array( 'status' => $status, 'media[]' => "#{$image}" );
$parameters = array( 'status' => $status, 'media[]' => file_get_contents($image) );
$response = $this->api->post( 'statuses/update_with_media.json', $parameters );
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
}
The message I get from twitter is :
Ooophs, we got an error: Update user status failed! Twitter returned an error. 403 Forbidden: The request is understood, but it has been refused.
How Can I get more precise info about error ?
Does anybody allready success in sending a picture attached to a tweet ?
Thanks !
Hugo
Thanks #Heena for making myself wake up on this question, I MADE IT ;)
function setUserStatus( $status )
{
if(is_array($status))
{
$message = $status["message"];
$image_path = $status["image_path"];
}
else
{
$message = $status;
$image_path = null;
}
$media_id = null;
# https://dev.twitter.com/rest/reference/get/help/configuration
$twitter_photo_size_limit = 3145728;
if($image_path!==null)
{
if(file_exists($image_path))
{
if(filesize($image_path) < $twitter_photo_size_limit)
{
# Backup base_url
$original_base_url = $this->api->api_base_url;
# Need to change base_url for uploading media
$this->api->api_base_url = "https://upload.twitter.com/1.1/";
# Call Twitter API media/upload.json
$parameters = array('media' => base64_encode(file_get_contents($image_path)) );
$response = $this->api->post( 'media/upload.json', $parameters );
error_log("Twitter upload response : ".print_r($response, true));
# Restore base_url
$this->api->api_base_url = $original_base_url;
# Retrieve media_id from response
if(isset($response->media_id))
{
$media_id = $response->media_id;
error_log("Twitter media_id : ".$media_id);
}
}
else
{
error_log("Twitter does not accept files larger than ".$twitter_photo_size_limit.". Check ".$image_path);
}
}
else
{
error_log("Can't send file ".$image_path." to Twitter cause does not exist ... ");
}
}
if($media_id!==null)
{
$parameters = array( 'status' => $message, 'media_ids' => $media_id );
}
else
{
$parameters = array( 'status' => $message);
}
$response = $this->api->post( 'statuses/update.json', $parameters );
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
}
To make it work you have to do like this :
$config = "/path_to_hybridauth_config.php";
$hybridauth = new Hybrid_Auth( $config );
$adapter = $hybridauth->authenticate( "Twitter" );
$twitter_status = array(
"message" => "Hi there! this is just a random update to test some stuff",
"image_path" => "/path_to_your_image.jpg"
);
$res = $adapter->setUserStatus( $twitter_status );
Enjoy !
I did not understand it for hybridauth then I used this library
https://github.com/J7mbo/twitter-api-php/archive/master.zip
Then I was successful using code below: (appears elsewhere in stack)
<?php
require_once('TwitterAPIExchange.php');
$settings= array(
'oauth_access_token' => '';
'oauth_access_secret' => '';
'consumer_key' => '';
'consumer_secret' => '';
// paste your keys above properly
)
$url_media = "https://api.twitter.com/1.1/statuses/update_with_media.json";
$requestMethod = "POST";
$tweetmsg = $_POST['post_description']; //POST data from upload form
$twimg = $_FILES['pictureFile']['tmp_name']; // POST data of file upload
$postfields = array(
'status' => $tweetmsg,
'media[]' => '#' . $twimg
);
try {
$twitter = new TwitterAPIExchange($settings);
$twitter->buildOauth($url_media, $requestMethod)
->setPostfields($postfields)
->performRequest();
echo "You just tweeted with an image";
} catch (Exception $ex) {
echo $ex->getMessage();
}
?>

cakephp2 can't get file data array through $this->request->data

usually, we get all the data we need from $this->request->data. but if I'm using ajax file upload, I can't get that data e.g: tmp_name, size, etc.
my javascript code is like:
function uploadFile(file_blob_chunk, file_name, file_part, total_file_chunk, file_id) {
fd = new FormData();
fd.append("file_for_upload", file_blob_chunk);
fd.append("somestring", "This is some extra data");
xhr = new XMLHttpRequest();
xhr.open("POST", "files/index/" + file_id + '/' + file_part, true);
//Onload happened after file finished uploaded
xhr.onload = function(e) {
//alert(file_name + "done");
};
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
}}, false);
xhr.send(fd);
}
and in FilesController.php
public function index($file_id = null, $file_part = null) {
if ($this->request->is('post')) {
//I can't use $this->request->data, to get the file details
}
}
If I use
debug($this->request->data);
I will only get
array(
'somestring' => 'This is some extra data'
)
I can't get the file data
Unless Im using debug($_FILES), I won't get
array(
'file_for_upload' => array(
'name' => 'blob',
'type' => 'application/octet-stream',
'tmp_name' => 'C:\xampp\tmp\phpAC42.tmp',
'error' => (int) 0,
'size' => (int) 9304862
)
)
If you want to use $this->request->data your post data should be in the format cake expects, eg: data[Model][some_field]
you have CustomField

Drupal.attachBehaviors not effect to returned ajax form

I'm working on Drupal 7, I have a form constructed like this
function qt_debate_response_form($form, &$form_state, $node_id){
$form['node_id'] = array(
'#type' => 'value',
'#value' => $node_id,
);
$form['response_body'] = array(
'#type' => 'textarea',
'#required' => TRUE,
'#row' => 4,
'#default_value' => '',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Post'),
'#ajax' => array(
'callback' => 'qt_debate_response_form_js',
'wrapper' => 'response-message-' . $node_id,
'method' => 'append',
'effect' => 'fade',
),
);
return $form;
}
And an ajax callback function to add new comment
function qt_debate_response_form_js($form, $form_state) {
global $user;
$body_text = $form_state['values']['response_body'];
$node_id = $form_state['values']['node_id'];
$message_js = '
<script language="javascript" type="text/javascript">
qt_debate_response_load_new_item(' . $node_id . ',' . $user->uid . ');
jQuery(".response-form-wrapper textarea").val("");
</script>';
$comment = new stdClass();
$comment->nid = $form_state['values']['node_id']; // Node Id the comment will attached to
$comment->cid = 0;
$comment->pid = 0;
$comment->uid = $user->uid;
$comment->is_anonymous = 0;
$comment->homepage = '';
$comment->status = COMMENT_PUBLISHED;
$comment->language = LANGUAGE_NONE;
$comment->subject = text_summary($body_text, null, 60);
$comment->comment_body[$comment->language][0]['value'] = $body_text;
$comment->comment_body[$comment->language][0]['format'] = 'filtered_html';
comment_submit($comment);
comment_save($comment);
$output = $message_js;
return $output;
}
here are my Javascript that load new created comment into Div (ajax)
function qt_debate_user_post_load_new_items(debate_id) {
// get the latest comment id in context
$top_comment = jQuery(".view-debate-user-posts .views-row").first();
$top_comment_id = jQuery(".nid-field-hidden", $top_comment).html();
jQuery.ajax({
type: "GET",
url: "/qt_debate/ajax/load_new_items/" + debate_id + "/" + $top_comment_id,
data: "",
success: function(html){
$new_items = jQuery(".view-content", html);
jQuery("form", $new_items).attr("action","/debate/199");
jQuery(".form-submit", $new_items).attr("id","edit-submit--5");
if ($new_items.html() != null) {
html = '<div class="new_items_wrapper" style="display: none">' + $new_items.html() + '</div>';
if (jQuery(".view-debate-user-posts .view-content").length == 0) {
jQuery(".view-debate-user-posts .view-empty").remove();
jQuery(".view-debate-user-posts").append('<div class="view-content"></div>');
}
jQuery(".view-debate-user-posts .view-content").prepend(html);
jQuery(".view-debate-user-posts .view-content .new_items_wrapper").fadeIn(500, function() {
jQuery(".views-row", this).unwrap();
Drupal.attachBehaviors();
});
}
},
});
var t = setTimeout("qt_debate_user_post_load_new_items(" + debate_id + ")", 30000)
}
The hook_menu which is return the views content to jQuery call back
function qt_debate_ajax_load_new_items() {
$debate_id = arg(3);
print views_embed_view('debate_user_posts_load_new_items_', 'default', array($debate_id));
exit(0);
}
View template file, i also return a new form inside
print drupal_render(drupal_get_form('qt_debate_response_form', $row->nid));
The return view content rendered good, with Drupal.attachBehaviors in Javascript, all others effect in returned view content also work well. Except the form submit ajax.
Can any one help please ? The attachBehaviors not work with return ajax form.
Thanks so much!
Drupal.attachBehaviors(context);
basically re-runs any functions defined by
Drupal.behaviors.yourFunctionName = function(context) {
$('div.someSelectorclass:not(.already-processed-class)', context).addClass('already-processed-class').bind(someMethod);
}
and these methods must add a selector [already-processed-class] to test for whether the bind(); [ or click(function(e){}); or each(function(){}); or whatever ] has already been added. The "context" is to pass less-than 'document' - say, if your new content is known to be inside a smaller context that will still be found by original behaviors function: in this example I could pass the parent container selector of my new 'div.someSelectorclass'
Drupal.attachBehaviors('div.parentContainerClass');
instead of
Drupal.attachBehaviors(document);

Resources