И так рассказываю, что я менял в WebKit-е, и что у меня получилось (надеюсь может кому-то пригодится).
Пишу я софтину, которая должна автоматом заполнять эл. хтмл форм, в том числе и поле <input type=file>(эл. FileUpload). Как известно доступ к value этого тега только ReadOnly! А так как webkit предоставляет доступ к хтмл эл. только через яваскрипт, то и шансов как либо изменить значение этого атрибута нет!
Сутки я потратил на поиски в гугле хоть каких либо солюшинов, позволяющих мне решить эту проблему, но увы ни чего не нашел... Решил я сам раскопать исходники. Программист я еще тот
- 2 мес. как работаю с С++ и Qt, поэтому в успехе уверен не был. Но все оказалось не так страшно, и в течении суток, после нескольких экспериментов, путем проб и ошибок, а так же кропотливого изучения кода (для меня кропотливого
), решения был найдены! Может не самые оптимальные и элегантные - но все же работоспособные и позволяющее изменять значения value для <input type="file"..> из Qt приложения.
Судя по выдачам гугла я не первый кто сталкивается с такой проблемой, и как вариант там предлагают использовать IE приложениях. IE позволяет забивать нужные данные через буфер... Но как быть если софт должен быть кроссплатформенным?
Поэтому я решил добить WebKit и заставить его работать так как надо мне! Чем и хочу поделится с вами...
НО перед тем как я выложу код этого хака, хочу сделать ВАЖНОЕ замечание (хоть и так очевидно, что безопасность WebKit нарушена!) -
Не используйте хак в приложениях полноценных веб браузеров! Используйте этот хак только в тех случаях, когда известны адресса загружаемых ресурсов.
В самом конце рекомендация, как можно немного обезопасить клиента использующего приложение с таким WebKit-ом.
Ну и собственно, что и как нужно менять:
Вариант 1:(объясняю оч подробно, что таким новичкам как я было понятно
)
1. Идем в: cd %QTDIR%\src\3rdparty\webkit\WebCore\html
2. Скачиваем приложенный файл - HTMLInputElement.cpp
3. Заменяем оригинальный HTMLInputElement.cpp на наш, скаченный.
4. Теперь нужно перекомпилить WebKit, для этого:
- заходим в %QTDIR%
- выполняем команду: configure -release -platform win32-g++ -no-vcproj -webkit -nomake demos -nomake examples -fast
- Ждем пока выполнится configure, после чего выполняем make (или mingw32-make )
- Ждем 2~5 часов пока все пересобирется (хочу заметить, что последующие вызовы make будут пересобирать WebKit быстрее - за 10 мин., пока вы не перекофиг. qt снова)
Если кому нужен уже скомпиленный QtWebKit4.dll, могу скинуть на мыло, его вес в архиве 4 метра.
Все! Запускаем прогу с WebKit и проверяем -
создаем файлик - test.html c кодом:
<html><head><title>Changing input file</title></head>
<body><form>
<div>fileField: <input type="file" name="fileField" id="fileField"></div>
<div><input type="button" value="Setup new fileField value" onClick="document.getElementById('fileField').value='c:/image/smale.gif'">(c:/image/smale.gif)</div>
<div><input type="button" value="View fileField value" onClick="document.getElementById('info').value=document.getElementById('fileField').value"></div>
<div>Info:<input id="info"></div><div>If it works good u can see in Info just file name - smale.gif.</div></form></body></html>
Теперь можем проверить правильно ли WebKit отправляет файл на сервер:
Создаем файлик - test.php с таким кодом:
<html><head><title>Test UploadFile</title></head>
<body>
<?
$fotos_dir = "fotos/";
$foto_name = $fotos_dir.basename($_FILES['myfile']['name']);
$foto_light_name = basename($_FILES['myfile']['name']);
$foto_tag_preview = "<img src=\"$foto_name\" border=\"1\">";
if(isset($_FILES["myfile"])) {
$myfile = $_FILES["myfile"]["tmp_name"];
$myfile_name = $_FILES["myfile"]["name"];
$myfile_size = $_FILES["myfile"]["size"];
$myfile_type = $_FILES["myfile"]["type"];
$error_flag = $_FILES["myfile"]["error"];
echo "<pre>";
print_r($_FILES["myfile"]);
echo "</pre><br>";
if($error_flag == 0) {
$DOCUMENT_ROOT = $_SERVER['DOCMENT_ROOT'];
$upfile = getcwd()."/fotos/".basename($_FILES["myfile"]["name"]);
if (!move_uploaded_file($_FILES['myfile']['tmp_name'], $upfile)){echo "Error".$error_by_file; exit;}
echo "<b>:</b> ".$fotos_dir." <br /><b>:</b> ".$foto_light_name."<br />";
echo "<br /><small>:</small> <br />$foto_tag_preview<br /><br />";}}
?>
<form action="test.php" method="post" enctype="multipart/form-data" name="form1" id="form1">
<p>fileUpload:<input type="file" name="myfile" id="myfile" />(dont touch it!)</p>
<p>Path to local file: <small>(c:/images/smale.gif)</small><br />
<input type="text" name="fs" id="fs" /><input type="button" value="Setup fileUpload" onClick="document.getElementById
('myfile').value=document.getElementById('fs').value"/></p>
<p><input type="submit" name="button" id="button" value="Submit" /></p>
</form>
</body>
</html>
заливаем его на сервак и открываем в нашем вебките, ищем на компе файл изображения и указываем в Path to local file: полный путь к файлу. Жмем SetUp fileUpload и Submit. Вуаля - файлик закачен на сервак, и нам показан. Значит все ОК!
Важные замечания:Обратите внимание, что после изменения значения value, WebKit все еще отображается текст No file selected. Я сейчас ищу способы и это исправить и как только найду выложу здесь. Но несмотря на это все работает.
Что б снизить риск, того что файлы могут быть стырины с компа клиента, использующего софт с "подчиканым" WebKit-ом, можно применить такой прием:
1. Придумать строку ключ, типа YZxeFOWk4XTDRsHDWhy и передовать ее вместе с нужными данными, разделив их напрмер "@". Например:
YZxeFOWk4XTDRsHDWhy@c:/images/smile.gif
2. в файле HTMLInputElement добавить проверку на присудствие ключа в переданной строке:
//my://////////////////////////////////////////////////////////
if (inputType() == FILE){
m_fileList->clear();
//////////////////add key checker://////////////////////
String skey="YZxeFOWk4XTDRsHDWhy";
size_t found;
found = value.find(skey);
if(found!=string::npos){
m_fileList->append(File::create(myKeyRemover(value))); //вырезает кей
m_value = constrainValue(value);
if (inputType() == FILE && inDocument())
document()->updateRendering();
setValueMatchesRenderer();
}
///////////// end key checker ////////////////////////////////
}
else {
m_value = constrainValue(value);
if (isTextField() && inDocument())
document()->updateRendering();
}
//my end///////////////////////////////////////////////
... я не проверял код этого пример на работоспособность, и не претендую на его безупречность, возможны и другие более оптимальные варианты, придумайте сами!
... вот такой мой первый топик на этом форуме
,
... а вообще оч хороший форум, я столько всего полезного тут узнал!!!