Any workarounds for the Safari HTML5 multiple file upload bug? - html

After weeks of tweaking I finally gave up. I just couldn't fix my multiple file upload on safari, which really bothered me because my code worked perfectly as it should on other browsers, except on safari. Then I have just recently discovered that its not my code that has the problem. Its a Safari bug. Safari 5.1.+ can't read the html5 multiple attribute (or something like that). So users can't use the multiple upload feature, BUT, can properly upload a single file.
few links that discuss the issue:
https://github.com/moxiecode/plupload/issues/363
file input size issue in safari for multiple file selection
It seems that this bug has been around for quite some time. So I was wondering if there are workarounds available for this at the moment that some of you maybe are aware of? Because I can't find any. The only option available i found is to NOT use multiple attribute for Safari 5.1.+ users. Do you guys have any better ideas?
UPDATE
Safari 5.1.7 is the last version Apple made for the Windows OS. They did not continue to build current versions of Safari for Windows. Finding a fix for this bug for me is not necessary since Real Safari users are updated to the latest version of the browser(no facts), and just give a separate upload for those who are still using this outdated version, to not sacrifice the modern features of your application.

This is oldish question, but ... hack-type workaround is below.
Just remove multiple attribute for Safari, turnig it into MSIE<=9 little brother (non-XHR).
Rest of browsers will not be affected.
When Safari finally fixes problem, all you have to do is remove this hack::code and go back to standard input code.
here is standard input sample:
<input class="fileupload-input" type="file" name="files[]" multiple />
jQuery solution:
Just place it somewhere on a page, where you have files input tag.
you may read more here: How to detect Safari, Chrome, IE, Firefox and Opera browser?
$(document).ready(function () {
if (Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')>0);
$('.fileupload-input').removeAttr("multiple");
});
PHP solution
you will need some code to id browser I used a class I got one in github (MIT)
get it here: https://github.com/gavroche/php-browser
$files = '<input class="fileupload-input" type="file" name="files[]" multiple />';
if (Browser::getBrowser() === Browser::SAFARI) {
$files = '<input class="fileupload-input" type="file" name="files[]" />';
}
echo $files
That is all.

It seems that there is another issue that can be messing around. iOS Safari multiple file uploads always use the name "image.jpg" for all uploaded files. It may seem only one file uploaded in the server side but this is not what happened: it has been uploaded all files with the same name!
So, the workaround comes into the server side: just change the destination filename with a new generated name.
I am working with Flask and Python, so I use the standard formula.
#app.route("/upload",methods=['POST'])
def upload():
files = request.files.getlist('files[]')
for file in files:
if file and allowed_file(file.filename):
filename = generate_filename(file.filename)
file.save( os.path.join(app.config['UPLOAD_FOLDER'], new_album_id, filename))
return render_template('upload_ok.html')
Where generate_filaname has to be a function that creates a new filename with the same extension as the original one. For example:
def generate_filename(sample_filename):
# pick up extension from sample filename
ext = sample_filename.split(".")[-1]
name = ''.join( random.SystemRandom().choice(string.letters+string.digits) for i in range(16) )
return name + "." + ext
The same can be done in PHP, of course.

I ran into the image.jpg problem with asp.net. It may benefit someone. I was appending a non-unique hash to each image file to tie it to the record in the db. Works fine on every platform (our users are using, anyway), except when using Safari. I just appended a hash and a unique three digit string I pulled from the seconds part of DateTime to string:
if (!string.IsNullOrEmpty(ViewState["HashId"].ToString()))
{
string filepath = Server.MapPath("~/docs/");
HttpFileCollection uploadedFiles = Request.Files;
Span1.Text = string.Empty;
for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
try
{
if (userPostedFile.ContentLength > 0)
{
string timestamp = DateTime.UtcNow.ToString("fff",
CultureInfo.InvariantCulture);
//Span1.Text += "<u>File #" + (i + 1) + "</u><br>";
//Span1.Text += "File Content Type: " + userPostedFile.ContentType + "<br>";
//Span1.Text += "File Size: " + userPostedFile.ContentLength + "kb<br>";
//Span1.Text += "File Name: " + userPostedFile.FileName + "<br>";
userPostedFile.SaveAs(filepath + "\\" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
// Span1.Text += "Location where saved: " + filepath + "\\" + Path.GetFileName(userPostedFile.FileName) + "<p>";
InsertFilename("~/docs/" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName), ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
}
}
catch (Exception Ex)
{
Span1.Text += "Error: <br>" + Ex.Message;
}
}
BindImages();
SetAttchBitTrue();
Button4.Visible = true;
AttchStatus.Text = "This Record Has Attachments";
Button2.Visible = true;
Button3.Visible = true;
Panel1.Visible = false;
}
May be a better way, but we just have a small number of people uploading one - two, maybe three images per record in the database. Should work.

Related

GAS: Can you use searchFiles on a searchFiles result?

This question might be more of a logical problem than a function problem.
I have two sets of PDFs "bought" and "return".
I use this to search for them:
qsBought = "fullText contains 'Bought' and mimeType='" + MimeType.PDF + "'";
qsReturn = "fullText contains 'Return' and mimeType='" + MimeType.PDF + "'";
Every file also have one device type in them. i.e. computer, chromebook, mac or iPad:
I can search for this with:
qsComputer = "fullText contains 'Computer' and mimeType='" + MimeType.PDF + "'";
I then use this to save the search result into a variable.
myFiles = parentFolder.searchFiles(qsXxx)
The result is then pushed to a sheet (that works like a I expect).
while(myFiles.hasNext()) {
var file, fileName, s, t;
file = myFiles.next();
fileName = file.getName();
s = fileName.substr(0, fileName.lastIndexOf('.')) || fileName;
t = s.split(' - ');
push(output, t, dv, qs);
}
output = colum headers
t = the name of the filename split
dv = supposed to be the device
qs = bought/returned
On every line I want to push out the information about if the devices is returned or bought.
I'm think that I can do a searchFiles(device) on the previous searchFiles(bought/returned) to find all computers bought, then computers returned, chromebooks bought and so on...
I've tried
qsBoughtComputer = "fullText contains 'Bought' and fullText contains 'computer' and mimeType='" + MimeType.PDF + "'";
I don't think searchFiles() support multiple fullText queries in the same search.
I don't fully grasp the logic or how to work with only these functions. If possible, I prefer to work with Googles core functions and repositories (first-party).
Thankful for any help in this!
As #doubleunary said in the comments.
Why would it not work?
I should've tried the solution after I made all the necessary changes to the code...
As I stated in the beginning;
This question might be more of a logical problem than a function
problem.

How to program a URL? (For search query)

A co-worker of mine shared an autohotkey script (it's actually an exe file that runs on the background). Anyways, when I click the hotkeys it opens up a company webiste and creates a shared query for whatever's on the clipboard. I was wondering how this is done and how I can make my own.
I'm specially curious about the "URL" modification that includes all these search options:
https://<COMPANYWEBSITE>/GotoDocumentSearch.do
That's the URL where I can search (sorry it's restricted and even if I link it you cant access it).
Anyways, after I set up all my options and stuff and click the search button I get the following URL:
https://<COMPANYWEBSITE>/DocumentSearch.do
I inspected the website source and this is the function that's called when I press the search button:
function preSubmitSearch(docPress) {
document.pressed = docPress;
// setup local doc types for submit by lopping over multi selects and building json data string
var localDocTypesJson = "{";
var sep = "";
jQuery(".localTypeSel").each(function (i) {
var selLocalTypes = jQuery(this).multiselect("getChecked");
// get doc type code from id ex. 'localTypeSel_PD'
//window.console.log("this.id=" + this.id);
var tmpArr = this.id.split("_");
var docTypeCode = tmpArr[1];
var selLocalTypesCnt = selLocalTypes.length;
if (selLocalTypesCnt > 0) {
var localTypes = "";
var sep2 = "";
for (var i2 = 0; i2 < selLocalTypesCnt; i2++) {
localTypes += sep2 + "\"" + selLocalTypes[i2].value + "\"";
sep2 = ",";
}
localDocTypesJson += sep + "\"" + docTypeCode + "\": [" + localTypes + "]";
sep = ",";
}
});
localDocTypesJson += "}";
jQuery("#localDocTypesJson").val(localDocTypesJson);
}
HOWEVER, the working code that was shared with me (that was written ages ago by some employee who's not here anymore). Has the following URL when I use the autohotkey:
https://<COMPANYWEBSITE>/DocumentSearch.do?searchType=all&localDocTypesJson=7D&formAction=search&formInitialized=true&searchResultsView=default&btn_search=Search&docName=*<CLIPBOARD>*&wildcards=on&docRevision=&latestRevOnly=true&docProjectNumber=&docEngChangeOrder=&docLocation=&findLimit=500&docTypes=Customer+Drawing&docTypes=Production+Drawing&docTypes=Manufacturing+Process+Document&docTypes=Specification+Or+Standard
Note: replaced text with "CLIPBOARD" for clarification.
I was wondering if that's a type of "URL-programming" or how can I make a direct URL that prompts for the search results from the website? is that Javascript? or how is that programmed? (I know Swift and some Java, but have never really used Javascript).
It doesn't seem like you are asking an AutoHotKey (AHK) question, but to give you an AHK example you can copy, here is how I would use AHK to use Google.com to search for whatever is in my clipboard:
wb := ComObjCreate("InternetExplorer.Application")
wb.Visible := true
wb.Navigate("https://www.google.com/search?q=" . StrReplace(Clipboard, " ", "+") . "", "")
Note, the URL format includes the query ("?q=whatever+you+had+in+Clipboard") in it with spaces replaced by "+"s.
Hth,

[Qt][QMYSQL] Deployed app - Driver not loaded

First of all, many thanks for those who will take time to help me on this topic. I've searched a lot on many different forums before posting here but it seems I'm missing something.
Well, I'm working on Windows 7 (64 bits) with Qt5.5 / MySQL Server 5.6.
And I use MinGW 5.5.0 32 bits on Qt Creator (auto detected).
It's not a matter of building the drivers, it's done and it works perfectly for the dev.! :-)
I can reach my BD, do any query that I want and retrieve/insert all the data.
I'm facing to a matter of deploying my application on other computers.
I know that I have to put qsqlmysql.dll in a folder "sqldrivers" placed in my app. directory. Such as placing libmysql.dll in this directory too.
So I have something like the following
App directory
App.exe
libmysql.dll
Qt5Core.dll
Qt5Gui
Qt5Sql
Qt5Widget
libwinpthread-1.dll
libstdc++-6.dll
libgcc_s_dw2-1.dll
platforms
qwindow.dll
sqldrivers
qsqlmysql.dll
BUT when I release the application and I try to run it from another computer which I used to develop, I have a "Driver not loaded" error...
As far now, I have really no idea what I've missed...
So please, if anyone could give me some, it would be really really appreciated!
I let you the part of the code which is really useful, just in case...
main.cpp
QApplication a(argc, argv);
Maintenance w;
w.show();
return a.exec();
Maintenance.cpp
void Maintenance::login(){
int db_select = 1;
this->maint_db = Database(db_select);
/* All that follow is linked to the login of user... */
}
Database.cpp
Database::Database(int default_db)
{
this->db = QSqlDatabase::addDatabase("QMYSQL");
switch(default_db){
case 0:
this->db.setHostName("XXX.XX.XXX.XX");
this->db.setDatabaseName("maintenance_db");
this->db.setUserName("USERNAME");
this->db.setPassword("PASSWORD");
this->db.setPort(3306);
break;
// Only to make some trials in local
case 1:
this->db.setHostName("127.0.0.1");
this->db.setDatabaseName("maintenance_db");
this->db.setUserName("USERNAME");
this->db.setPassword("PASSWORD");
break;
}
/* I've added the following code to try to solve the problem
I retrieve that the available drivers are: QMYSQL / QMYSQL3
But all the information about the DB are empty (due to the unloaded driver I assume.)
And the error from *lastError()* is "Driver not loaded"
*/
QString my_drivers;
for(int i = 0; i < QSqlDatabase::drivers().length(); i++){
my_drivers = my_drivers + " / " + QSqlDatabase::drivers().at(i);
}
QString lib_path;
for(int i = 0; i < QApplication::libraryPaths().length(); i++){
lib_path = lib_path + " / " + QApplication::libraryPaths().at(i);
}
QString start = QString::number(QCoreApplication::startingUp());
QMessageBox::information(0, "BDD init",
"Drivers available: " + my_drivers
+ " \nHostname: " + this->db.hostName()
+ "\nDB name: " + this->db.databaseName()
+ "\nUsername: " + this->db.userName()
+ "\nPW: " + this->db.password()
+ "\n\n" + lib_path + "\n" + start
);
if(this->db.isOpen()){
QMessageBox::information(0, "BDD init", "Already open.");
}
else{
if(this->db.open()){
QMessageBox::information(0, "BDD init", "Opened.");
}
else{
QMessageBox::critical(0, "BDD init", "Not opened.\n" + this->db.lastError().text());
}
}
}
There are at least 3 possible solutions:
Find all .dll paths are correct with your favourite process monitor
Make sure all .dll is in the same arch as your .exe, which is x86 (32bit)
Debug with QPluginLoader
Simplest way to create "deploy" folder for you windows Qt5 aplication is using windeployqt tool
Create empty directory, copy your app.exe file and than run windeployqt app.exe
Check out the docs http://doc.qt.io/qt-5/windows-deployment.html#the-windows-deployment-tool

Simple Obfuscation Of String Constants in Flash

I am not a F
lash expert.
I have a FLA file of a game coded in ActionScript 3.
The game has a string inside, "www.mywebsite.com".
I want that when someone opens this FLA and searches for ".com" or "mywebsite.com" to find nothing. So I have decided to encode that string somehow. But I never coded in Flash, so I have no idea what to start with and Google isn't helping.
Basically all I want to do is replace this line:
var url1 = 'www.mywebsite.com';
With something like this and be functional.
var url1 = base64_decode('asdahwiyadwaeawr==');
Even a XOR or other simple string manipulation algorithm would be good.
What options do I have without importing any non-standard libraries into Flash?
Anyone looking through your code at something like var url = BlaBla_decode("cvxcvxc"); can simply replace it with var url = "www.HisWebsite.com...
So I guess you're supposing no one will be going through your script line by line but instead search for ".com" (Which would make him a really lazy jerk)!
A simple solution is to come up with a function that would return "www.MyWebsite.com" without writing it;
Something like:
var url:String = youAreStupid();
function youAreStupid():String
{
return String(f(22) + f(22) + f(22) + "extra.extra" + f(12) + f(24) + f(22) + f(4) + f(1) + f(18) + f(8) + f(19) + f(4) + "extra.extra" + f(2) + f(14) + f(12)).replace(/extra/g, "");
}
function f(n:Number):String
{
return String.fromCharCode("a".charCodeAt(0) + n);
}
I can't but say this would be lame way to protect your document, and I suggest you keep a comment at the top of your Script (something clearly visible) : // You won't find it YOU ARE STUPID
Now if he's smart enough to search for youAreStupid, that means he's entitled to change it :p
Of course there's also the simpler:
String("-Ow-Mw-Gw-!.-Ym-Oy-Uw-Ae-Rb-Es-Si-Ot-Se-T.-Uc-Po-Im-D").replace(/-./g, "");
but that's no fun!!!

Flex requests by URLLoader not being well received on server side

today's question involves URLLoader requests using encrypted strings.
when I encrypt a string I get the following result:
1Kx4dfp5OC7ox0zb0lWzzzlnoPLcoPGE1MrAKOtl3h6SPcFmEdpLnUROSKpPrCl70VHRxrKzhsxHHlb1MRp3++JkvYZ++ghBEG2zbVhyaqQ/0+NDrJ+0cLt3g9THe9POohN6Ufcq9TcnmZVvIFXllg4HrjVNfQrhQCNwxuBgWBf2DRc4eq6hKzEgyLdlllQFc9ssUFlPD3wOBqoI22r+7N82sI3pqsQYBq5VlKHHreqD8Cq0gictnTFS3IqepASGARKyuCIPDCa4zE76VeQV5zgvkFfjDww+C1uZ8PUgjH67DKYqUP9a6euf2v1jUpBrREnm4ZbLAXScDjvrJ11rWYyVXOLZy9nhy9qRBQRvdw+tnBThPTmvxaq+LAusF8IbvDpZgMrZ3buvThnXuSBGXZxaja7fk/FIlm4RSliDTSGySiizFHy7dJePXuV0c9MI6ciOYxmEIg64NnhBZtB8wipUDJWOpoytOD2/sNQBenjZbYN8291msYnbBG+alAOQmEBH5Mn4KyW1VQWE2lBGk9ML+SflND8UXfdHz5Q3psOcMZJxSAURKGq5tjA8KlPPOAdQuVPIcysg2/4lV25QGIdDttQVGrkP+ZHZcHIPTLLD+Vml+PJU/OAJGNPGlf3wawUo+bID0FKur8N6tNyu7Pnoocn7plDi6WSJgUAaYjI4=
I send it in, everything seems fine on Flex's end. But when I go to the serverside (logfiles, not allowed to change server-side code) to check what I'm getting, I end up with this:
1Kx4dfp5OC7ox0zb0lWzzzlnoPLcoPGE1MrAKOtl3h6SPcFmEdpLnUROSKpPrCl70VHRxrKzhsxHHlb1MRp3 JkvYZ ghBEG2zbVhyaqQ/0 NDrJ 0cLt3g9THe9POohN6Ufcq9TcnmZVvIFXllg4HrjVNfQrhQCNwxuBgWBf2DRc4eq6hKzEgyLdlllQFc9ssUFlPD3wOBqoI22r 7N82sI3pqsQYBq5VlKHHreqD8Cq0gictnTFS3IqepASGARKyuCIPDCa4zE76VeQV5zgvkFfjDww C1uZ8PUgjH67DKYqUP9a6euf2v1jUpBrREnm4ZbLAXScDjvrJ11rWYyVXOLZy9nhy9qRBQRvdw tnBThPTmvxaq LAusF8IbvDpZgMrZ3buvThnXuSBGXZxaja7fk/FIlm4RSliDTSGySiizFHy7dJePXuV0c9MI6ciOYxmEIg64NnhBZtB8wipUDJWOpoytOD2/sNQBenjZbYN8291msYnbBG alAOQmEBH5Mn4KyW1VQWE2lBGk9ML SflND8UXfdHz5Q3psOcMZJxSAURKGq5tjA8KlPPOAdQuVPIcysg2/4lV25QGIdDttQVGrkP ZHZcHIPTLLD Vml PJU/OAJGNPGlf3wawUo bID0FKur8N6tNyu7Pnoocn7plDi6WSJgUAaYjI4=
at first glance they're the same, but if you check closely, the + gets replaced by a whitespace...
I've even tried switching the + for %2B but on the server-side it gets read as %2B, it isn't converted to a + (flex doesn't seem to function as a browser in this case).
Any kind of insight and help on this matter would be very appreciated.
The requests are being done as follows:
public function callService(callback:String, request:String):void{
var url:URLRequest = new URLRequest(server);
var requestedString:String = handlePluses(request);
url.useCache = false;
url.contentType = contentType;
url.method = method;
trace("sending: " + requestedString);
url.data += requestedString);
serverURL.addEventListener(IOErrorEvent.IO_ERROR, treatIO);
serverURL.dataFormat = URLLoaderDataFormat.TEXT;
serverURL.addEventListener(Event.COMPLETE, loadData);
serverURL.addEventListener(Event.CONNECT, function():void{trace("connected");});
try{
serverURL.load(url);
}catch(e:ArgumentError){trace("ArgError: " + e.message);}
catch(e:SecurityError){trace("SecError: " + e.message);}
catch(e:TimeoutEvent){trace("===========<Timeout>===========");}
}
we fixed this problem by switching the + character with a subset of escaped characters like \&\#.
this might be a problem to others attempting the same thing and trying to keep to a minimum size.