Security error
|
|
Just curious on how you overcame the security errors from the |
|
|
Are you trying to access images on a different domain to that which the javascript is running on? The only way I've found around it is to get the the image data using GM_xmlhttpRequest (since that works cross-domain) and then writing a decoder for the image type in javascript. In this megaupload script I wrote a basic GIF decoder, it only works for megaupload captcha GIFs because I was lazy and wrote the bare minimum to make it work, but it wouldn't take much to get it working on other GIFs. I also previously wrote a limited JPEG decoder (http://userscripts.org/scripts/show/38940) for a similar purpose when I was playing around with recaptcha. Edit: Also it just occurred to me you might not know you have to use unsafeWindow to create the canvas on. |
|
|
Yeah I have started playing around, and realized I will need to make a GIF decoder. I wonder if there are any online API's? Here a sample image in question: http://174.129.249.180/img/captcha_image.php?wi... Basically I want the script to "capture" the data of the image, so I can then upload it to my webserver without reloading the URL on any other IP address. I'm using PHP scripts on my server so maybe I can send the raw data and then just recompile the image using PHP... |
|
|
It would be much simpler to just send the raw data, once it's saved on the disk you should be able to just use the normal PHP image functions to read it. |
|
|
Hmm so how do I get the data to the server in one piece is the next question... So far this is my Javascript:
function init()
{
var image = document.getElementById('app8743457343_content').getElementsByTagName('img')[0];
GM_xmlhttpRequest({
method: 'GET',
url: image.src,
overrideMimeType: 'text/plain; charset=x-user-defined',
onload: function(xhr)
{
GM_xmlhttpRequest({
method: 'POST',
url: 'http://localhost/sites/test/captcha.php',
data: 'image='+encodeURIComponent(xhr.responseText),
headers:{'Content-type':'application/x-www-form-urlencoded'},
onload: function(xhr)
{
return;
}
});
return;
}
});
return;
};
init();
And my PHP I haven't really worked on yet, but so far:
<?php $image = stripslashes($_POST['image']); ?> $image now contains the data in text form, but how would I convert that into binary and compile it back into a displayable image? Time to read some documentation... :P
|
|
|
I'm really not a fan of PHP, but the easiest way would just be to write it to a tempfile and then use the imagecreatefromgif() function, or if you have PHP 5.1 and fopen wrappers enabled write the string to php://memory then rewind and read it back again with imagecreatefromgif() instead of saving it to file. There might be a better way to do it, but as I said I'm not much of a PHP user, in Python I'd accomplish it using StringIO. |
|
|
Oh, also I wasn't quite paying attention, I'm not sure if the way you have it will work or not, but you'll probably at least have to process the data on the PHP side to throw away the upper bytes of the characters, but PHP has very poor Unicode support so you might have some trouble there. You'd probably have better success processing the character data into the correct binary data in javascript (see how I've done it in my script, I didn't invent it but I can't remember where I first saw it) and then coverting it to base64 to post and back again in PHP. |
|
|
function data_array(data)
{
var data_array = [];
for (var i = 0; i < data.length; i++)
data_array.push(data[i].charCodeAt(0) & 0xff);
return data_array;
}
So this is your function that processes it into the correct binary data? Obviously this put's it into a array for processing, but what would I need to do to get it ready to write to a file? |
|
|
Once it's been converted into an array using that function each element is 1 byte of the image, you could try just joining up the array into a string and posting that, if that works then the string will contain the raw image data. However I believe (I could be totally wrong, I have never tested it) that sending binary data using GM_xmlhttpRequest is problematic, which is why I suggested you convert it to base64 in javascript before posting it then convert it back afterwards in PHP. There are lots of examples of base64 implementation in javascript so I won't bother going into detail there. |
|
|
Yeah the |
|
|
Oh, yes, I totally forgot there was a built in base64 function now. Anyway, you don't have to do anything, those are the actual bytes of the image file. The reason you have to go through that process to convert the response text you get from GM_xmlhttpRequest is it's encoded in multibyte characters, but only the lowest byte is the actual image data. Oce you've got that you could just write it to a file and it will be an exact copy of the original. |
|
|
OK. So with this code:
function init()
{
var image = document.getElementById('app8743457343_content').getElementsByTagName('img')[0];
GM_xmlhttpRequest({
method: 'GET',
url: image.src,
overrideMimeType: 'text/plain; charset=x-user-defined',
onload: function(xhr)
{
var data=btoa(data_array(xhr.responseText).join(''));
return;
}
});
return;
};
init();
The variable data should contain the data ready for transport to the PHP? Or am I missing something.
A good tutorial on the relationship between data in character and binary form would be a good find about now. This is all new to me haha. Thanks for all your help so far. |
|
|
The data field should then contain the image encoded in base64, yes. Character data isn't really any different than binary data until you start getting into Unicode or other multibyte encodings, where one character can be represented by many bytes. The problem is GM_xmlhttpRequest (and normal XMLHttpRequest) acts "smart" in that instead of just giving you the exact data that it receives, it tries to read it as if it were UTF8 text, so it might say "oh, look, these two bytes mean it's an "å" character" and treat multiple bytes of the data as if they were a single character, and in some cases miss out some bytes if they aren't able to be decoded in that character set. That's why you override the character set to x-user-defined, because every byte will directly map to a character code that directly corresponds to its correct value - it maps the bytes 0x00 to 0xff to the UTF8 character codes 0xf700 to 0xf7ff, so all we have to do is take the bottom byte to get back to the original data. In theory if there were a 8-bit character encoding where every value from 0-255 is a valid character we could override to that and it would be even better, because there would be no extra processing to do, but others have looked for one and failed to find it. |
|
|
OK I tried writing the data to a file using PHP, and the image apparently contains errors. My PHP:
<?php
$image = stripslashes($_GET['image']);
$data = base64_decode($image);
$fp = fopen("test.gif",'w');
fwrite($fp, $data);
fclose($fp);
?>
I also tried directly inserting the base64 string into a data URL and that didn't work either. E.g. data:image/gif;base64,[base64_string_here]
I'm starting to run out of ideas haha. I echo'ed 7173705655977004501980060102281641541322121821801161307618017818023619420492122681321501241881661562121982201961902041641661561401421088411452124142108196178172236202220108130842282022282121902041801661481321381001081267614815011619618219625220222076110441161341001801621489212276220206236148158140164162148220198220921145224420221276106442281901961881861962441982121881741642041901961721661481321421081961861882281942041801741806810228212190196124134921881781802361982202041781722282062282201902041801701641561501242041861961241381001001227622020223624420622820419021217216616413214612417215814022018618811613492236198204100122601881701568411860108134921801701561961861962522062207611452156158140172162140220202228921186824420622013214611668106361881821961001267616415813221218618811613084140150132212202228148146116841146019618218823620622810813092228202236212194220180166156108126841481501247611052116138100220198228921186024420222019617416420419020417216615613214211668102361881821882041821802282062362201942041561541241241381082041942121721701642361982121001226818817016419618620425220622815616214817216214810012684000440000700450072541280130131132133134135136137138139133470142144143146145148147150149152151154153149133126679595171268559831303689646482141161161022716095361314714461226210122748450318014019514534246030200602009547139130201210202210614646212203211601091552221571823996209601132021702161202230302272292008014299211245202602619513814213052377921015814073183461419210830010319261611321223017612415520015821291192371988511635141189105230142561461291082201947221861228338131341260741521223211571143371472136411817612916046601477702403691121381955714624920926150619618872168110210317811862951165724199671422369175625723424216204182524660196401275134122541057822041144166157178124012822220316421919316315614442512837701371272012081215811637104185413516912118421023224591781012721181148026237313310211222917102168018767181332438033176107661454104512331151763518162341898142131382291566943100544831614111921017822178321941943816621724172157803931641291093160225215289475211547524316067182081051994721231191255610821610614435171852864021320122230165246682061481085310812915755139116019850118213162221129210602281343618957551992171171291232397713001140157821591321736021849211132326961182244896381413201815486921092787421624267131316117135138241063920013424568501362794248229127160972542091311244293531991381542162428221760241222115912814514120211856519518123244321662315724180670612240136242363631548212204150159336910819312926522006146211751011199785250200166933088915635130237116105190418723872115198161022812895882102100230582093912921815814114914221817615876719368130810114422442010424010078282852909531210145106137150200161322294960188227711722112126419316744106135171931522271130150211647191372021609612811560120129128173176225582222582190801664573226675481236641924706491476651001311053322217867661402311022126721210213160618316022574771793534136140415315859205308568101642553427165148125468138204188131133145501141882491301524544241695411320819245631101281121691991031001952159897961871991665129331131813117988197206205203159114242112671400196282083010222822814201721482023757371176211922481022038710110771544010539177143247149243521213706418020936832271972115246883120723716448176132146832222157150762666120619618402241619956227248447220422960236177322262169980136123620911612510121231701212310014102921112812823015315114416935211000230181671033018681281272532301410632128052860105139263783313202881642191761371642392208641312617718316610210215719173924013004736113255415165892039516916937142821542301874017359186120245160771595124725102152489821147665724313919173179248126391231262511481912392271961402321757932059 |
|
|
Ah, it appears using the join method of an array converts the byte to an ASCII representation of that number before joining it up, so the byte is 0xff is converted into three characters: 0x32, 0x35, 0x35 (the character codes for 2, 5, 5). That obviously isn't what you want. What I'd suggest is change the data_array function to give you a string from the start, just start off in an empty string instead of an empty array and append each character like
If that doesn't work then you'll have to write a base64 function that can operate on arrays instead of strings. |
|
|
Actually I just looked at the fromCharCode page on the Mozilla site and it says it expects "A sequence of numbers that are Unicode values.", so I have a feeling the above code won't quite work. I suspect the only way to do it then is to convert directly from the data array to base64. |
|
|
Yay, it does work. I'll do more testing and post back here. Thanks again for all the help. |
|
|
Oh, good. I thought it might just return undefined or something for values that aren't valid Unicode characters. |
|
|
Shn wrote: Nope. I can now successfully 'capture' image data from a GM_xmlhttpRequest();. Cheers for the help!
|
|
|
Shn wrote: The problem with the join(); method I tried, was that it was never put back into it's respective character with String.fromCharCode();. I would have had to run a additional loop over the data array to turn it into the binary string.
|
|
|
Well, the problem is the way it converts integers into a string. Instead of converting them into the characters that the integer represents it converts them into an ASCII representation of those numbers. There's no reason that's "the" way that a number should be converted to a string, it's just the way it's done in javascript. |
![]() ![]() |
so whats the full working code right now, im curious :? |

