Change programmatically IID_IHTMLInputFileElement value - javascript

I tried for several days to programmatically put a file path into a input type file element into a CHtmlView control (IE). I have tried this:
IHTMLInputFileElement* pInputElem = NULL;
hr = pElemDispatch->QueryInterface(IID_IHTMLInputFileElement, (void**)&pInputElem);
CString sFile(_T("C:\\Flaviu\\SomeFile.txt"));
BSTR bstrFilesAttribute = sFile.AllocSysString();
hr = pInputElem->put_value(bstrFilesAttribute); // hr is S_OK though
SysFreeString(bstrFilesAttribute);
but didn't work, I mean there is no SomeFile.txt chosen on input file.
I have read on several sites that I cannot edit or set value on an input type file element for security reason.
Somewhere, someone, suggested a simple solution: to make a copy of the original web page, and edit html source code and replace input type file element to an input type text. Which I have done. I only have to solve "action" attribute on form:
Original html source code:
<form name="uf" method="POST" action="/WS6ERT/SomeFile.do" enctype="multipart/form-data">
<div style="background-color: #c6c6c6; padding: 5px">
<span>Choose file:</span> <span> <input type="file" name="linkdoc" size="75" value=""></span><span><input type="submit" value="Send"></span>
</div>
</form>
and I made a copy, and I replaced input type file, with input type text:
<form name="uf" method="POST"
action="https://originalsite.com/WS6ERT/SomeFile.do" enctype="multipart/form-data">
<div style="background-color: #c6c6c6; padding: 5px">
<span>Choose file::</span> <span> <input type="text" name="linkdoc">
</span><span><input type="submit" value="Send"></span>
</form>
The important tags attribute: "action="
Of course that is not correct what I have written in my html source, because my path is pointing on the original file, which I didn't edit...
Is there a way to solve this issue? To put programmatically a file path into an input type file on a CHtmlView view? Or how to overcome this problem?
Last Edit: Can I setup the file with javascript ? I saw here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#attr-files that is possible to setup a file in files attribute. But I don't know how to do that ...

If you have a handle to CHtmlView* then use CHtmlView::Navigate2 or CHtmlView::Navigate
This should do the job unless html control is busy with a previous request, for example you already made a Navigate request and the html control is not finished processing that request. In the case, you can override CHtmlView::OnNavigateComplete2, which lets you know the html control is finished with the previous navigation request, and it can receive a new request. Alternatively you could use a wait function to wait for the control to finish using the for loop shown below.
CString filename = _T("C:\\Test\\test.html");
CStringW content = LR"(<html><body> content </body></html>)";
//optional: in case the control is busy with previous request
for(int i = 0; i < 100; i++)
{
MSG msg;
while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
if(!AfxGetThread()->PumpMessage())
break;
CFile test;
if(test.Open(filename, CFile::modeNoTruncate | CFile::modeWrite))
break;
}
CFile fout;
if(fout.Open(filename, CFile::modeCreate | CFile::modeWrite))
{
content = LR"(<html><body> content UPDATE </body></html>)";
CStringA utf8 = CW2A(content, CP_UTF8);
fout.Write(utf8, utf8.GetLength());
fout.Close();
htmlview->Navigate(filename, 0, NULL);
}

Related

Selenium Python - Upload image when element seems to be hidden

So basically I have problem uploading some photo using Selenium Python
input element seems to be hidden in the page so the .sendkeys method at still I run into some errors.
this is html code of the input element
<div data-react-class="ImageUploadForm" data-react-props="{}" data-react-cache-id="ImageUploadForm-0">
<input class="hidden" type="file" accept="image/jpeg, image/jpg, image/png, image/gif">
<button class="btn btn-lemonfrog text-lg" type="button">Upload photo</button>
</div>
base_path = Path(file).parent
filepath = (basepath / "../core/attachments/clientstackphoto.jpeg").resolve()
hiddenuploaderinput.sendkeys(filepath)
right now after running above code I'm getting type error :
value = (PosixPath('........./core/attachments/clientstackphoto.jpeg'),)
def keys_to_typing(value):
"""Processes the values that will be typed in the element."""
typing = []
for val in value:
if isinstance(val, Keys):
typing.append(val)
elif isinstance(val, int):
val = str(val)
for i in range(len(val)):
typing.append(val[i])
else:
for i in range(len(val)):
E TypeError: object of type 'PosixPath' has no len()
../../venv/lib/python3.7/site-packages/selenium/webdriver/common/utils.py:150: TypeError
I expect to upload photo successfully, maybe some js injection will help ?
Based on your error message, I'm not entirely convinced the error message is caused by the hidden file input. If it were, I would expect an ElementNotVisibleException.
However, I do see that the input is hidden, so we should run some JS to reveal the input and perhaps we can rule that out as a potential issue.
Code to show image input
fileInput = driver.find_element_by_xpath("//input[#type='file']")
# display file input so we can send keys
driver.execute_script("arguments[0].style.display = 'block';", fileInput)
Alternatively, you may need to execute script on the class attribute instead:
driver.execute_script("arguments[0].setAttribute('class', 'visible')", fileInput)
Once you execute JS to make the file input visible, you can just send_keys to it like any other input:
fileInput.send_keys("PATH/TO/FILE/HERE")

How to change a HTML-element to the selection of a File-Dialog?

I am currently working on a python program that uses a html/css interface which is connected through eel. It requires the user to load a file to analyze. In order to show the user on the User interface which file was selected, I want to show the name of the file (or the path) after the selection process is done.
Since I am new to this, I found a simple filedialog on the internet (probably somewhere here on Stackoverflow) that uses JQuery to select the path to a file. The selection works fine and my program can work with that information if the file that is being selected is located in the same folder as the html file, as this circumvents fakepath errors and I do not know a way around it.
I want to display the selected path underneath the button once it has been selected. However, in the current configuration it displays [object object] right after clicking the "Browserino" button and not the selected path or (ideally) the selected filename.
The HTML document contains:
<div class="col">
<button id="button" class="btn btn-primary" onclick="clicked();">Browserino</button>
<input id="file-input" type="file" name="name" style="display: none;" />
<small id="pathway" class="form-text text-muted">invisible</small>
</div>
And the main.js has this function to work with:
function clicked(){
var path = String($('#file-input').trigger('click'));
document.getElementById('pathway').innerHTML = path;
document.getElementById('pathway').style.visibility = 'visible';
}
I have also tried the follwing in the main.js, but it does not do the trick for me:
function clicked(){
String($('#file-input').trigger('click'));
var file_input = document.getElementById('file-input').value;
var filepath = file_input.replace(/^.*[\\\/]/, '');
document.getElementById('pathway').innerHTML = filepath;
}
Thanks for all the comments before, I hope this edit helps clarify the problem. Any help is appreciated. Thx.

Input Type = File, FileUpload disappears after JavaScript

In an MVC application, I'm having users upload a file and then doing some error handling. This portion works fine.
The file input is:
<div class="col-md-3" id="browsebutton">
<label class="btn btn-primary btn-file">
Browse<input type="file" id="FileUpload" name="FileUpload" class="" />
</label></div>
I want to display the file name as soon as a user chooses it, so I added this bit of JavaScript and an onChange="getFileName():
function getFileName() {
str = document.getElementById("FileUpload").value;
var filename = str.substring(12, str.length);
document.getElementById("browsebutton").innerHTML += filename;
}
var coll = document.getElementsByClassName("collapsible");
var i;
This properly displays the filename. However, as soon as I add this, the FileUpload becomes null in my controller.
How is this JavaScript interfering with my file upload?
Replace this line:
document.getElementById("browsebutton").innerHTML += filename;
With:
var fnSpan = document.createElement("span");
fnSpan.innerText = filename;
document.getElementById("browsebutton").appendChild(fnSpan);
The way you're doing it, you're setting the contents of the innerHtml, which ends up clearing the input (the input's value isn't part of the innerHtml string). Use DOM manipulation methods instead.
You can also make the span a permanent part of the DOM, and simply set its innerText in your code.

Inserting value into a JavaScript file template and generating a new file

I have a web application with a form and an number of inputs:
<form action="">
Title1:<br>
<input type="text" name="title1">
<input type="text" name="title1Description">
<br>
Title2:<br>
<input type="text" name="title2">
<input type="text" name="title3Description">
<br>
Title3:<br>
<input type="text" name="title3">
<input type="text" name="title3Description">
<br>
<button type="button">Insert an Generate!</button>
</form>
I also have a JavaScript file which acts as a template:
template.js
function myFunction(p1, p2) {
return p1 * p2;
}
function mySecondFunction(p3, p4) {
return p3 - p4;
}
var myData = {
*title1* : {
Title: *title1*,
Description: *title1Description*
},
*title2* : {
Title: *title2*,
Description: *title2Description*
},
}
When a user clicks the button, how can i generate a copy of template.js insert the values the user has entered into the xxxxx parts of var myData, and prompt the user to download the newly generate file?
I can use AngularJS if this makes it easier than jQuery?
I'm not going to write the entire code, but here's what I'm thinking about:
When the button is clicked, you could pass the values e.g. using GET variables. Click here to find out how that works.
Next you can save the entire code of the js file in a String, and use the values from the GET variables.
And last but not least, use the following code to download a file containing the generated String str:
window.open('data:text/csv,' + encodeURIComponent(str));
Edit
The solution above doesn't make it possible to store the file with a custom file name. If you want to accomplish that, you would need a little work around, because you need to use the download attribute of <a>:
var link = document.createElement("a");
var csv = "data:text/csv;charset=utf-8," + str;
link.setAttribute("href", encodeURI(csv));
link.setAttribute("download", "template.js"); //custom file name here
link.click();
Be aware that not every browser supports the download attribute. Check here to find out more.
Edit2
Okay, I wrote the code, because I was having a good day and not much to do ;) You can find it here (jsFiddle was giving me troubles)

Image as a post variable

I am working on a site where there is a feature for users to be able to sign directly on the webpage using a canvas free form pen tool. When users click the 'apply signature' button the signature that the user drew is converted into an image and saved on the page as an <img src=""> (as you can see in the code below). Up until this point everything works great.
The problem is, When the user submits the form, I am trying to get the newly created canvas image to submit with it as a post variable and render on the process.php page as the signature that was signed. It appears that image (toDataURL()) gets passed as a post variable, but for some reason it does not render on the process.php page. It appears like the image source is not found.
I am new to javascript and I have been trying to fix this problem for days now, I would appreciate any help with fixing this. Many thanks in advance!
Markup
<div class="signature-field">
Sign:
<span class="sketch-container">
<canvas id="simple_sketch" width="350" height="100"></canvas>
</span>
Date: <input name="signature-date" type="text"><br/>
<div class="signature-buttons">
<span class="save-signature">Apply Signature | </span>
<span class="reset-canvas">| Reset Signature</span><br/>
</div>
</div>
<form method="post" action="process.php">
<input type="text" name="fname">
<input id="signature" name="signature" type="hidden">
<input type="submit">
</form>
JavaScript
$(function () {
var sktch = $('#simple_sketch').sketch();
var cleanCanvas = $('#simple_sketch')[0];
$('.save-signature').click(function () {
/* replace canvas with image */
var canvas = document.getElementById("simple_sketch");
var img = canvas.toDataURL("image/png");
$('#simple_sketch').replaceWith('<img src="' + img + '"/>');
$('.signature-buttons').replaceWith('');
document.getElementById("signature").value = $('.sketch-container').html();
});
});
I'm not quite sure what you're doing here, but if you want to post the image data through the hidden signature field, simply do this:
document.getElementById("signature").value = document.getElementById("simple_sketch").toDataURL("image/png");
As right now, it looks like you're posting the image data including <img> tags ("<img src="<DataUrl>"/>")
How about your server-side code, is the img param output empty? Are you sure the img data is being sent through the request? Try some packet sniffing tool like Fiddler or Wireshark and analyze the contents of the request (You can also take a quick look with Firebug).
Perhaps you could try some other approach to convert the img data:
https://developer.mozilla.org/en-US/docs/HTML/Canvas/Pixel_manipulation_with_canvas

Categories