diff --git a/src/components/codecs/AbstractCodecsModel.cpp b/src/components/codecs/AbstractCodecsModel.cpp index 3ab0e893d..64ef126c3 100644 --- a/src/components/codecs/AbstractCodecsModel.cpp +++ b/src/components/codecs/AbstractCodecsModel.cpp @@ -20,9 +20,9 @@ * Author: Ronan Abhamon */ -#include "../../app/paths/Paths.hpp" -#include "../../utils/Utils.hpp" -#include "../core/CoreManager.hpp" +#include "app/paths/Paths.hpp" +#include "components/core/CoreManager.hpp" +#include "utils/Utils.hpp" #include "AbstractCodecsModel.hpp" @@ -94,7 +94,7 @@ void AbstractCodecsModel::setRecvFmtp (int id, const QString &recvFmtp) { Q_ASSERT(id >= 0 && id < mCodecs.count()); QVariantMap &map = mCodecs[id]; - shared_ptr codec = ::getCodecFromMap(map); + shared_ptr codec = getCodecFromMap(map); if (codec) { codec->setRecvFmtp(Utils::appStringToCoreString(recvFmtp)); map["recvFmtp"] = Utils::coreStringToAppString(codec->getRecvFmtp()); @@ -179,25 +179,21 @@ void AbstractCodecsModel::addCodec (shared_ptr &codec) { void AbstractCodecsModel::addDownloadableCodec ( const QString &mime, - const QString &fileName, + const QString &encoderDescription, const QString &downloadUrl, - const QString &encoderDescription + const QString &installName ) { QVariantMap map; - map["mime"] = mime; - map["fileName"] = fileName; map["downloadUrl"] = downloadUrl; map["encoderDescription"] = encoderDescription; + map["installName"] = installName; + map["mime"] = mime; mCodecs << map; } QVariantMap AbstractCodecsModel::getCodecInfo (const QString &mime) const { - // TODO: Remove me in 4.2 release. - qDebug() << "Enable me in 4.2 release."; - return QVariantMap(); - for (const auto &codec : mCodecs) if (codec.value("mime") == mime) return codec; diff --git a/src/components/codecs/AbstractCodecsModel.hpp b/src/components/codecs/AbstractCodecsModel.hpp index d5ad9daab..a8b98b979 100644 --- a/src/components/codecs/AbstractCodecsModel.hpp +++ b/src/components/codecs/AbstractCodecsModel.hpp @@ -67,7 +67,12 @@ protected: ) override; void addCodec (std::shared_ptr &codec); - void addDownloadableCodec (const QString &mime, const QString &fileName, const QString &downloadUrl, const QString &encoderDescription); + void addDownloadableCodec ( + const QString &mime, + const QString &encoderDescription, + const QString &downloadUrl, + const QString &installName + ); QString getCodecsFolder () const; diff --git a/src/components/codecs/AudioCodecsModel.hpp b/src/components/codecs/AudioCodecsModel.hpp index 989c0234a..1b9d13656 100644 --- a/src/components/codecs/AudioCodecsModel.hpp +++ b/src/components/codecs/AudioCodecsModel.hpp @@ -32,7 +32,6 @@ class AudioCodecsModel : public AbstractCodecsModel { public: AudioCodecsModel (QObject *parent = Q_NULLPTR); - ~AudioCodecsModel () = default; private: void updateCodecs (std::list> &codecs) override; diff --git a/src/components/codecs/VideoCodecsModel.cpp b/src/components/codecs/VideoCodecsModel.cpp index dac88a72f..5488c4e28 100644 --- a/src/components/codecs/VideoCodecsModel.cpp +++ b/src/components/codecs/VideoCodecsModel.cpp @@ -24,9 +24,11 @@ #include #include -#include "../../app/paths/Paths.hpp" -#include "../../utils/Utils.hpp" -#include "../core/CoreManager.hpp" +#include "app/paths/Paths.hpp" +#include "components/core/CoreManager.hpp" +#include "components/file/FileDownloader.hpp" +#include "components/file/FileExtractor.hpp" +#include "utils/Utils.hpp" #include "VideoCodecsModel.hpp" @@ -35,11 +37,11 @@ using namespace std; namespace { - constexpr char cH264FileName[] = "openh264"; constexpr char cH264Description[] = "Provided by CISCO SYSTEM,INC"; #ifdef Q_OS_LINUX constexpr char cLibraryExtension[] = "so"; + constexpr char cH264InstallName[] = "libopenh264.so"; #ifdef Q_PROCESSOR_X86_64 constexpr char cPluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-1.7.0-linux64.4.so.bz2"; #else @@ -47,9 +49,10 @@ namespace { #endif // ifdef Q_PROCESSOR_X86_64 #elif defined(Q_OS_WIN) constexpr char cLibraryExtension[] = "dll"; + constexpr char cH264InstallName[] = "openh264.dll"; #ifdef Q_OS_WIN64 constexpr char cPluginUrlH264[] = "http://ciscobinary.openh264.org/openh264-1.7.0-win64.dll.bz2"; - #elif defined(Q_OS_WIN32) + #else constexpr char cPluginUrlH264[] = "http://ciscobinary.openh264.org/openh264-1.7.0-win32.dll.bz2"; #endif // ifdef Q_OS_WIN64 #endif // ifdef Q_OS_LINUX @@ -58,56 +61,74 @@ namespace { VideoCodecsModel::VideoCodecsModel (QObject *parent) : AbstractCodecsModel(parent) { load(); - // update codec if there is a new version + // Update codec if it exists a new version. #if defined(Q_OS_LINUX) || defined(Q_OS_WIN) - QString codecsFolder = Utils::coreStringToAppString(Paths::getCodecsDirPath()); - QString filePath = QDir::cleanPath(codecsFolder) + QDir::separator() + cH264FileName + ".txt"; - - if(updateCodecVersion(filePath, cPluginUrlH264)) { - mFileDownloader = new FileDownloader(); - mFileDownloader->setUrl(QUrl(cPluginUrlH264)); - mFileDownloader->setDownloadFolder(codecsFolder); - mFileExtractor = new FileExtractor(); - mFileExtractor->setExtractFolder(codecsFolder); - - mFileDownloader->download(); - QObject::connect(mFileDownloader, &FileDownloader::downloadFinished, this, &VideoCodecsModel::extract); - QObject::connect(mFileDownloader, &FileDownloader::downloadFailed, this, &VideoCodecsModel::installFileFailed); - QObject::connect(mFileExtractor, &FileExtractor::extractFinished, this, &VideoCodecsModel::endInstallFile); - QObject::connect(mFileExtractor, &FileExtractor::extractFailed, this, &VideoCodecsModel::installFileFailed); - } - #endif + updateCodecVersion("H264", cPluginUrlH264, cH264InstallName); + #endif } -VideoCodecsModel::~VideoCodecsModel () { - qInfo() << QStringLiteral("Delete VideoCodecsModel"); +bool VideoCodecsModel::updateCodecVersion ( + const QString &mime, + const QString &downloadUrl, + const QString &installName +) { + QString codecsFolder = Utils::coreStringToAppString(Paths::getCodecsDirPath()); + QString versionFilePath = codecsFolder + mime + ".txt"; + QFile versionFile(versionFilePath); - if (mFileDownloader) mFileDownloader = nullptr; + if (!versionFile.exists() && !QFileInfo::exists(codecsFolder + cH264InstallName)) + return false; // Must be downloaded one time before. - if (mFileExtractor) mFileExtractor = nullptr; -} - -bool VideoCodecsModel::updateCodecVersion(const QString &filePath, const QString &newVersion) { - QFile versionFile(filePath); - - if (!versionFile.exists()) return false; - if (!versionFile.open(QIODevice::ReadOnly)) { - qWarning() << QStringLiteral("Unable to read version from file."); + if (!versionFile.open(QIODevice::ReadOnly)) + qWarning() << QStringLiteral("Unable to read codec version from: `%1`.").arg(versionFilePath); + else if (!QString::compare(QTextStream(&versionFile).readAll(), downloadUrl, Qt::CaseInsensitive)) return false; - } - QString version; - QTextStream s1(&versionFile); - version.append(s1.readAll()); - versionFile.close(); - return QString::compare(newVersion, version, Qt::CaseInsensitive)>0; + qInfo() << QStringLiteral("Updating `%1` codec...").arg(mime); + + FileDownloader *fileDownloader = new FileDownloader(this); + fileDownloader->setUrl(QUrl(cPluginUrlH264)); + fileDownloader->setDownloadFolder(codecsFolder); + + FileExtractor *fileExtractor = new FileExtractor(fileDownloader); + fileExtractor->setExtractFolder(codecsFolder); + fileExtractor->setExtractName(cH264InstallName); + + QObject::connect(fileDownloader, &FileDownloader::downloadFinished, this, [fileExtractor](const QString &filePath) { + fileExtractor->setFile(filePath); + fileExtractor->extract(); + }); + + QObject::connect(fileDownloader, &FileDownloader::downloadFailed, this, [fileDownloader]() { + fileDownloader->deleteLater(); + }); + + QObject::connect(fileExtractor, &FileExtractor::extractFinished, this, [fileDownloader, fileExtractor, versionFilePath, downloadUrl]() { + QFile versionFile(versionFilePath); + if (!versionFile.open(QIODevice::WriteOnly)) { + qWarning() << QStringLiteral("Unable to write codec version in: `%1`.").arg(versionFilePath); + return; + } + if (versionFile.write(downloadUrl.toStdString().c_str(), downloadUrl.length()) == -1) { + fileExtractor->remove(); + versionFile.close(); + versionFile.remove(); + } + + fileDownloader->remove(); + fileDownloader->deleteLater(); + }); + + QObject::connect(fileExtractor, &FileExtractor::extractFailed, this, [fileDownloader]() { + fileDownloader->remove(); + fileDownloader->deleteLater(); + }); + + fileDownloader->download(); + + return true; } -void VideoCodecsModel::installFileFailed() { - qWarning() << QStringLiteral("Unable to install codec `%1` .").arg(cH264FileName); -} - - void VideoCodecsModel::updateCodecs (list> &codecs) { CoreManager::getInstance()->getCore()->setVideoPayloadTypes(codecs); } @@ -134,30 +155,14 @@ void VideoCodecsModel::load () { addCodec(codec); // Add downloadable codecs. - // TODO: Remove me in 4.2 release. - qDebug() << "Enable downloadable codecs in 4.2 release."; - return; - #if defined(Q_OS_LINUX) || defined(Q_OS_WIN) if (find_if(codecs.begin(), codecs.end(), [](const shared_ptr &codec) { return codec->getMimeType() == "H264"; }) == codecs.end()) - addDownloadableCodec("H264", cH264FileName, cPluginUrlH264, cH264Description); + addDownloadableCodec("H264", cH264Description, cPluginUrlH264, cH264InstallName); #endif } -void VideoCodecsModel::extract(const QString &filePath) { - mFileExtractor->setFile(filePath); - mFileExtractor->extract(); -} - -void VideoCodecsModel::endInstallFile() { - mFileDownloader->remove(); - mFileDownloader->writeVersion(cH264FileName); - mFileExtractor->rename(cH264FileName); - reload(); -} - void VideoCodecsModel::reload () { beginResetModel(); load(); diff --git a/src/components/codecs/VideoCodecsModel.hpp b/src/components/codecs/VideoCodecsModel.hpp index 8c7bea723..02037dd4d 100644 --- a/src/components/codecs/VideoCodecsModel.hpp +++ b/src/components/codecs/VideoCodecsModel.hpp @@ -25,9 +25,6 @@ #include "AbstractCodecsModel.hpp" -#include "../file/FileDownloader.hpp" -#include "../file/FileExtractor.hpp" - // ============================================================================= class VideoCodecsModel : public AbstractCodecsModel { @@ -35,20 +32,14 @@ class VideoCodecsModel : public AbstractCodecsModel { public: VideoCodecsModel (QObject *parent = Q_NULLPTR); - ~VideoCodecsModel (); private: void updateCodecs (std::list> &codecs) override; - bool updateCodecVersion (const QString &filePath, const QString &newVersion); + bool updateCodecVersion (const QString &mime, const QString &downloadUrl, const QString &installName); + void load (); - void extract(const QString &filePath); - void installFileFailed(); - void endInstallFile(); void reload () override; - QTimer *mTimer = nullptr; - FileDownloader *mFileDownloader = nullptr; - FileExtractor *mFileExtractor = nullptr; }; #endif // VIDEO_CODECS_MODEL_H_ diff --git a/src/components/file/FileDownloader.cpp b/src/components/file/FileDownloader.cpp index ed0e856d5..5681e2301 100644 --- a/src/components/file/FileDownloader.cpp +++ b/src/components/file/FileDownloader.cpp @@ -20,14 +20,14 @@ * Author: Danmei Chen */ -#include "../../app/paths/Paths.hpp" -#include "../../utils/Utils.hpp" -#include "../core/CoreManager.hpp" +#include "app/paths/Paths.hpp" +#include "components/core/CoreManager.hpp" +#include "utils/Utils.hpp" #include "FileDownloader.hpp" // ============================================================================= -using namespace std; + namespace { constexpr char cDefaultFileName[] = "download"; } @@ -105,25 +105,6 @@ bool FileDownloader::remove () { return mDestinationFile.exists() && !mDestinationFile.isOpen() && mDestinationFile.remove(); } -void FileDownloader::writeVersion(const QString &newFileName) { - QFile versionFile; - - versionFile.setFileName( - QDir::cleanPath(mDownloadFolder) + QDir::separator() + newFileName + ".txt" - ); - - Q_ASSERT(!versionFile.isOpen()); - if (versionFile.exists()) versionFile.remove(); - if (!versionFile.open(QIODevice::WriteOnly)) { - qWarning() << QStringLiteral("Unable to write version to file."); - return; - } - - string version = mUrl.toString().toStdString(); - versionFile.write(version.c_str(), qstrlen(version.c_str())); - versionFile.close(); -} - void FileDownloader::emitOutputError () { qWarning() << QStringLiteral("Could not write into `%1` (%2).") .arg(mDestinationFile.fileName()).arg(mDestinationFile.errorString()); diff --git a/src/components/file/FileDownloader.hpp b/src/components/file/FileDownloader.hpp index b64f51a75..691a875d0 100644 --- a/src/components/file/FileDownloader.hpp +++ b/src/components/file/FileDownloader.hpp @@ -19,8 +19,10 @@ * Created on: February 6, 2018 * Author: Danmei Chen */ -#ifndef FILE_DOWNLOADER_H_ + +#ifndef FILE_DOWNLOADER_H_ #define FILE_DOWNLOADER_H_ + #include #include @@ -40,11 +42,16 @@ class FileDownloader : public QObject { Q_PROPERTY(bool downloading READ getDownloading NOTIFY downloadingChanged); public: + FileDownloader (QObject *parent = Q_NULLPTR) : QObject(parent) {} + Q_INVOKABLE void download (); Q_INVOKABLE bool remove(); - Q_INVOKABLE void setUrl (const QUrl &url); - Q_INVOKABLE void setDownloadFolder (const QString &downloadFolder); - Q_INVOKABLE void writeVersion (const QString &newFileName); + + QUrl getUrl () const; + void setUrl (const QUrl &url); + + QString getDownloadFolder () const; + void setDownloadFolder (const QString &downloadFolder); signals: void urlChanged (const QUrl &url); @@ -56,10 +63,6 @@ signals: void downloadFailed(); private: - QUrl getUrl () const; - - QString getDownloadFolder () const; - qint64 getReadBytes () const; void setReadBytes (qint64 readBytes); @@ -88,4 +91,5 @@ private: QPointer mNetworkReply; QNetworkAccessManager mManager; }; -#endif // FILE_DOWNLOADER_H_ \ No newline at end of file + +#endif // FILE_DOWNLOADER_H_ diff --git a/src/components/file/FileExtractor.cpp b/src/components/file/FileExtractor.cpp index b953edcdb..1e6b997a1 100644 --- a/src/components/file/FileExtractor.cpp +++ b/src/components/file/FileExtractor.cpp @@ -112,12 +112,13 @@ void FileExtractor::extract () { // 2. Open output file. // TODO: Deal with existing files. - Q_ASSERT(!mDestinationFile.isOpen()); + Q_ASSERT(!mDestinationFile.isOpen()); mDestinationFile.setFileName( - QDir::cleanPath(mExtractFolder) + QDir::separator() + fileInfo.completeBaseName() + QDir::cleanPath(mExtractFolder) + QDir::separator() + ( + mExtractName.isEmpty() ? fileInfo.completeBaseName() : mExtractName + ) ); - //TODO not sure - mDestinationFile.remove(); + if (!mDestinationFile.open(QIODevice::WriteOnly)) { emitOutputError(); return; @@ -133,14 +134,6 @@ bool FileExtractor::remove () { return mDestinationFile.exists() && !mDestinationFile.isOpen() && mDestinationFile.remove(); } -bool FileExtractor::rename (const QString &newFileName) { - const QString filePath = mExtractFolder + newFileName + "." + QFileInfo(mDestinationFile).suffix(); - //delete old file - QFile oldFile(filePath); - if(oldFile.exists()) oldFile.remove(); - return mDestinationFile.exists() && !mDestinationFile.isOpen() && mDestinationFile.rename(filePath); -} - QString FileExtractor::getFile () const { return mFile; } @@ -173,6 +166,22 @@ void FileExtractor::setExtractFolder (const QString &extractFolder) { } } +QString FileExtractor::getExtractName () const { + return mExtractName; +} + +void FileExtractor::setExtractName (const QString &extractName) { + if (mExtracting) { + qWarning() << QStringLiteral("Unable to set extract name, a file is extracting."); + return; + } + + if (mExtractName != extractName) { + mExtractName = extractName; + emit extractNameChanged(mExtractName); + } +} + qint64 FileExtractor::getReadBytes () const { return mReadBytes; } diff --git a/src/components/file/FileExtractor.hpp b/src/components/file/FileExtractor.hpp index 61eeed507..026580fd8 100644 --- a/src/components/file/FileExtractor.hpp +++ b/src/components/file/FileExtractor.hpp @@ -38,6 +38,7 @@ class FileExtractor : public QObject { Q_PROPERTY(QString file READ getFile WRITE setFile NOTIFY fileChanged); Q_PROPERTY(QString extractFolder READ getExtractFolder WRITE setExtractFolder NOTIFY extractFolderChanged); + Q_PROPERTY(QString extractName READ getExtractName WRITE setExtractName NOTIFY extractNameChanged); Q_PROPERTY(qint64 readBytes READ getReadBytes NOTIFY readBytesChanged); Q_PROPERTY(qint64 totalBytes READ getTotalBytes NOTIFY totalBytesChanged); Q_PROPERTY(bool extracting READ getExtracting NOTIFY extractingChanged); @@ -48,24 +49,30 @@ public: Q_INVOKABLE void extract (); Q_INVOKABLE bool remove (); - Q_INVOKABLE bool rename (const QString &newFileName); - Q_INVOKABLE void setExtractFolder (const QString &extractFolder); - Q_INVOKABLE void setFile (const QString &file); + + QString getFile () const; + void setFile (const QString &file); + + QString getExtractFolder () const; + void setExtractFolder (const QString &extractFolder); + + QString getExtractName () const; + void setExtractName (const QString &extractName); signals: void fileChanged (const QString &file); + void extractFolderChanged (const QString &extractFolder); + void extractNameChanged (const QString &extractName); + void readBytesChanged (qint64 readBytes); void totalBytesChanged (qint64 totalBytes); + void extractingChanged (bool extracting); void extractFinished (); void extractFailed (); private: - QString getFile () const; - - QString getExtractFolder () const; - qint64 getReadBytes () const; void setReadBytes (qint64 readBytes); @@ -85,6 +92,7 @@ private: QString mFile; QString mExtractFolder; + QString mExtractName; QFile mDestinationFile; qint64 mReadBytes = 0; diff --git a/src/components/settings/SettingsModel.cpp b/src/components/settings/SettingsModel.cpp index e1b3a4920..b393383c0 100644 --- a/src/components/settings/SettingsModel.cpp +++ b/src/components/settings/SettingsModel.cpp @@ -772,7 +772,6 @@ QString SettingsModel::getSavedScreenshotsFolder () const { void SettingsModel::setSavedScreenshotsFolder (const QString &folder) { QString cleanedFolder = QDir::cleanPath(folder) + QDir::separator(); - mConfig->setString(UI_SECTION, "saved_screenshots_folder", Utils::appStringToCoreString(cleanedFolder)); emit savedScreenshotsFolderChanged(cleanedFolder); } @@ -789,7 +788,6 @@ QString SettingsModel::getSavedVideosFolder () const { void SettingsModel::setSavedVideosFolder (const QString &folder) { QString cleanedFolder = QDir::cleanPath(folder) + QDir::separator(); - mConfig->setString(UI_SECTION, "saved_videos_folder", Utils::appStringToCoreString(cleanedFolder)); emit savedVideosFolderChanged(cleanedFolder); } @@ -806,7 +804,6 @@ QString SettingsModel::getDownloadFolder () const { void SettingsModel::setDownloadFolder (const QString &folder) { QString cleanedFolder = QDir::cleanPath(folder) + QDir::separator(); - mConfig->setString(UI_SECTION, "download_folder", Utils::appStringToCoreString(cleanedFolder)); emit downloadFolderChanged(cleanedFolder); } diff --git a/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml b/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml index be5f6e7e9..8732bb9a3 100644 --- a/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml +++ b/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml @@ -16,8 +16,8 @@ DialogPlus { property alias downloadUrl: fileDownloader.url property alias installFolder: fileDownloader.downloadFolder property bool extract: false - property string fileName - property string newFileName + property string installName + property string mime property bool _installing: false property int _exitStatus: -1 // Not downloaded for the moment. @@ -32,8 +32,7 @@ DialogPlus { function _endInstall (exitStatus) { if (dialog.extract) { fileDownloader.remove() - fileDownloader.writeVersion(newFileName) - fileExtractor.rename(newFileName) + Utils.write(installFolder + mime + '.txt', downloadUrl) } dialog._exitStatus = exitStatus dialog._installing = false @@ -72,7 +71,7 @@ DialogPlus { str = qsTr('onlineInstallerFailedDescription') } - return str.replace('%1', dialog.fileName) + return str.replace('%1', dialog.mime) } height: OnlineInstallerDialogStyle.height width: OnlineInstallerDialogStyle.width @@ -112,14 +111,12 @@ DialogPlus { } Text { - id: text - property var target: fileDownloader - anchors.right: parent.right color: OnlineInstallerDialogStyle.column.text.color font.pointSize: OnlineInstallerDialogStyle.column.text.pointSize text: { + var target = progressBar.target var fileSize = Utils.formatSize(target.totalBytes) return Utils.formatSize(target.readBytes) + '/' + fileSize } @@ -133,7 +130,6 @@ DialogPlus { fileExtractor.file = filePath if (dialog.extract) { progressBar.target = fileExtractor - text.target = fileExtractor fileExtractor.extract() } else { dialog._endInstall(1) @@ -145,6 +141,7 @@ DialogPlus { id: fileExtractor extractFolder: dialog.installFolder + extractName: dialog.installName onExtractFailed: dialog._endInstall(0) onExtractFinished: dialog._endInstall(1) diff --git a/ui/scripts/LinphoneUtils/linphone-utils.js b/ui/scripts/LinphoneUtils/linphone-utils.js index beefa4cae..a87e3caea 100644 --- a/ui/scripts/LinphoneUtils/linphone-utils.js +++ b/ui/scripts/LinphoneUtils/linphone-utils.js @@ -104,9 +104,9 @@ function openCodecOnlineInstallerDialog (window, codecInfo, cb) { window.attachVirtualWindow(buildDialogUri('OnlineInstallerDialog'), { downloadUrl: codecInfo.downloadUrl, extract: true, - fileName: codecInfo.mime, - newFileName: codecInfo.fileName, - installFolder: VideoCodecsModel.codecsFolder + installFolder: VideoCodecsModel.codecsFolder, + installName: codecInfo.installName, + mime: codecInfo.mime }, function (status) { if (status) { VideoCodecsModel.reload() diff --git a/ui/scripts/Utils/utils.js b/ui/scripts/Utils/utils.js index e1b1d093d..17e703096 100644 --- a/ui/scripts/Utils/utils.js +++ b/ui/scripts/Utils/utils.js @@ -625,3 +625,11 @@ function unscapeHtml (str) { .replace(/"/g, '"') .replace(/'/g, ''') } + +// ----------------------------------------------------------------------------- + +function write (fileName, text) { + var request = new XMLHttpRequest(); + request.open('PUT', 'file://' + fileName, false); + request.send(text); +}