You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2013/12/05 01:58:15 UTC
[1/9] git commit: CB-5188:
Updated Branches:
refs/heads/master ac7cb43da -> 76baae969
CB-5188:
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/60f96e07
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/60f96e07
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/60f96e07
Branch: refs/heads/master
Commit: 60f96e078b5d2cd8cf1c22556fb76d62f473fbca
Parents: ac7cb43
Author: Steven Gill <st...@gmail.com>
Authored: Mon Oct 28 12:27:15 2013 -0700
Committer: Steven Gill <st...@gmail.com>
Committed: Mon Oct 28 12:27:15 2013 -0700
----------------------------------------------------------------------
plugin.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/60f96e07/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index 114b072..d1de8dd 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.file-transfer"
- version="0.3.4">
+ version="0.3.5-dev">
<name>File Transfer</name>
<description>Cordova File Transfer Plugin</description>
<license>Apache 2.0</license>
[7/9] git commit: added ubuntu support
Posted by st...@apache.org.
added ubuntu support
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/fee10fb6
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/fee10fb6
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/fee10fb6
Branch: refs/heads/master
Commit: fee10fb6d8d4db50a5ae5352bfee08329233856b
Parents: 4c259e7 4219ef3
Author: Steven Gill <st...@gmail.com>
Authored: Mon Dec 2 16:12:45 2013 -0800
Committer: Steven Gill <st...@gmail.com>
Committed: Mon Dec 2 16:12:45 2013 -0800
----------------------------------------------------------------------
plugin.xml | 6 +
src/ubuntu/file-transfer.cpp | 247 ++++++++++++++++++++++++++++++++++++++
src/ubuntu/file-transfer.h | 97 +++++++++++++++
3 files changed, 350 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/fee10fb6/plugin.xml
----------------------------------------------------------------------
diff --cc plugin.xml
index 7513bb0,c9a2019..34371bb
--- a/plugin.xml
+++ b/plugin.xml
@@@ -37,23 -35,12 +37,29 @@@
<source-file src="src/android/FileUploadResult.java" target-dir="src/org/apache/cordova/filetransfer" />
</platform>
+ <!-- amamzon-fireos -->
+ <platform name="amazon-fireos">
+ <config-file target="res/xml/config.xml" parent="/*">
+ <feature name="FileTransfer" >
+ <param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer"/>
+ </feature>
+ </config-file>
+
+ <config-file target="AndroidManifest.xml" parent="/*">
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ </config-file>
+
+ <source-file src="src/amazon/FileTransfer.java" target-dir="src/org/apache/cordova/filetransfer" />
+ <source-file src="src/android/FileProgressResult.java" target-dir="src/org/apache/cordova/filetransfer" />
+ <source-file src="src/android/FileUploadResult.java" target-dir="src/org/apache/cordova/filetransfer" />
+ </platform>
+
+ <!-- ubuntu -->
+ <platform name="ubuntu">
+ <header-file src="src/ubuntu/file-transfer.h" />
+ <source-file src="src/ubuntu/file-transfer.cpp" />
+ </platform>
+
<platform name="blackberry10">
<config-file target="www/config.xml" parent="/widget">
<feature name="FileTransfer" value="FileTransfer"></feature>
[8/9] git commit: CB-5466: Partial revert;
we're not ready yet for FS urls
Posted by st...@apache.org.
CB-5466: Partial revert; we're not ready yet for FS urls
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/4c11f54b
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/4c11f54b
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/4c11f54b
Branch: refs/heads/master
Commit: 4c11f54bd587008debf6e22e18199044711d0976
Parents: fee10fb
Author: Ian Clelland <ic...@chromium.org>
Authored: Wed Dec 4 08:50:38 2013 -0500
Committer: Ian Clelland <ic...@chromium.org>
Committed: Wed Dec 4 16:10:00 2013 -0500
----------------------------------------------------------------------
src/ios/CDVFileTransfer.h | 1 -
src/ios/CDVFileTransfer.m | 94 +++++++++++++++++++-----------------------
2 files changed, 43 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4c11f54b/src/ios/CDVFileTransfer.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h
index aa1cf9e..8e8211d 100644
--- a/src/ios/CDVFileTransfer.h
+++ b/src/ios/CDVFileTransfer.h
@@ -71,7 +71,6 @@ extern NSString* const kOptionsKeyCookie;
@property (nonatomic, copy) NSString* objectId;
@property (nonatomic, copy) NSString* source;
@property (nonatomic, copy) NSString* target;
-@property (nonatomic, copy) NSURL* targetURL;
@property (nonatomic, copy) NSString* mimeType;
@property (assign) int responseCode; // atomic
@property (nonatomic, assign) long long bytesTransfered;
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4c11f54b/src/ios/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m
index 2eec342..c50754f 100644
--- a/src/ios/CDVFileTransfer.m
+++ b/src/ios/CDVFileTransfer.m
@@ -20,15 +20,12 @@
#import <Cordova/CDV.h>
#import "CDVFileTransfer.h"
#import "CDVFile.h"
-#import "CDVLocalFilesystem.h"
#import <AssetsLibrary/ALAsset.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
#import <AssetsLibrary/ALAssetsLibrary.h>
#import <CFNetwork/CFNetwork.h>
-extern CDVFile *filePlugin;
-
@interface CDVFileTransfer ()
// Sets the requests headers for the request.
- (void)applyRequestHeaders:(NSDictionary*)headers toRequest:(NSMutableURLRequest*)req;
@@ -277,23 +274,31 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
NSString* server = [command.arguments objectAtIndex:1];
NSError* __autoreleasing err = nil;
- CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:source];
- NSObject<CDVFileSystem> *fs;
- if (sourceURL) {
- // Try to get a CDVFileSystem which will handle this file.
- // This requires talking to the current CDVFile plugin.
- fs = [filePlugin filesystemForURL:sourceURL];
- }
- if (fs) {
- [fs readFileAtURL:sourceURL start:0 end:-1 callback:^(NSData *fileData, NSString *mimeType, CDVFileError err) {
- if (err) {
+ // return unsupported result for assets-library URLs
+ if ([source hasPrefix:kCDVAssetsLibraryPrefix]) {
+ // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
+ ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
+ if (asset) {
+ // We have the asset! Get the data and send it off.
+ ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
+ Byte* buffer = (Byte*)malloc([assetRepresentation size]);
+ NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil];
+ NSData* fileData = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
+ [self uploadData:fileData command:command];
+ } else {
// We couldn't find the asset. Send the appropriate error.
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- } else {
- [self uploadData:fileData command:command];
}
- }];
+ };
+ ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
+ // Retrieving the asset failed for some reason. Send the appropriate error.
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ };
+
+ ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
+ [assetsLibrary assetForURL:[NSURL URLWithString:source] resultBlock:resultBlock failureBlock:failureBlock];
return;
} else {
// Extract the path part out of a file: URL.
@@ -304,17 +309,14 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
return;
}
-
+
// Memory map the file so that it can be read efficiently even if it is large.
NSData* fileData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&err];
-
+
if (err != nil) {
NSLog(@"Error opening file %@: %@", source, err);
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- } else {
- [self uploadData:fileData command:command];
}
+ [self uploadData:fileData command:command];
}
}
@@ -364,6 +366,13 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
NSString* objectId = [command.arguments objectAtIndex:3];
NSDictionary* headers = [command.arguments objectAtIndex:4 withDefault:nil];
+ // return unsupported result for assets-library URLs
+ if ([target hasPrefix:kCDVAssetsLibraryPrefix]) {
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"download not supported for assets-library URLs."];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ return;
+ }
+
CDVPluginResult* result = nil;
CDVFileTransferError errorCode = 0;
@@ -375,17 +384,14 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
targetURL = [NSURL URLWithString:target];
}
- NSURL* sourceURL = [NSURL URLWithString:source];
+ NSURL* url = [NSURL URLWithString:source];
- if (!sourceURL) {
+ if (!url) {
errorCode = INVALID_URL_ERR;
NSLog(@"File Transfer Error: Invalid server URL %@", source);
} else if (![targetURL isFileURL]) {
- CDVFilesystemURL *fsURL = [CDVFilesystemURL fileSystemURLWithString:target];
- if (!fsURL) {
- errorCode = FILE_NOT_FOUND_ERR;
- NSLog(@"File Transfer Error: Invalid file path or URL %@", target);
- }
+ errorCode = FILE_NOT_FOUND_ERR;
+ NSLog(@"File Transfer Error: Invalid file path or URL %@", target);
}
if (errorCode > 0) {
@@ -394,7 +400,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
return;
}
- NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:sourceURL];
+ NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
[self applyRequestHeaders:headers toRequest:req];
CDVFileTransferDelegate* delegate = [[CDVFileTransferDelegate alloc] init];
@@ -404,7 +410,6 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
delegate.objectId = objectId;
delegate.source = source;
delegate.target = target;
- delegate.targetURL = targetURL;
delegate.trustAllHosts = trustAllHosts;
delegate.connection = [NSURLConnection connectionWithRequest:req delegate:delegate];
@@ -517,6 +522,8 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
NSString* downloadResponse = nil;
NSMutableDictionary* uploadResult;
CDVPluginResult* result = nil;
+ BOOL bDirRequest = NO;
+ CDVFile* filePlugin;
NSLog(@"File Transfer Finished with response code %d", self.responseCode);
@@ -542,7 +549,8 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
self.targetFileHandle = nil;
DLog(@"File Transfer Download success");
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin makeEntryForURL:self.targetURL]];
+ filePlugin = [[CDVFile alloc] init];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin getDirectoryEntry:target isDirectory:bDirRequest]];
} else {
downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[command createFileTransferError:CONNECTION_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]];
@@ -611,23 +619,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
}
if ((self.direction == CDV_TRANSFER_DOWNLOAD) && (self.responseCode >= 200) && (self.responseCode < 300)) {
// Download response is okay; begin streaming output to file
- NSString *filePath = nil;
- CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:self.target];
- if (sourceURL && sourceURL.fileSystemType != -1) {
- // This requires talking to the current CDVFile plugin
- NSObject<CDVFileSystem> *fs = [filePlugin.fileSystems objectAtIndex:sourceURL.fileSystemType];
- filePath = [fs filesystemPathForURL:sourceURL];
- } else {
- // Extract the path part out of a file: URL.
- NSString* filePath = [self.target hasPrefix:@"/"] ? [self.target copy] : [[NSURL URLWithString:self.target] path];
- if (filePath == nil) {
- // We couldn't find the asset. Send the appropriate error.
- [self cancelTransferWithError:connection errorMessage:[NSString stringWithFormat:@"Could not create target file"]];
- return;
- }
- }
-
- NSString* parentPath = [filePath stringByDeletingLastPathComponent];
+ NSString* parentPath = [self.target stringByDeletingLastPathComponent];
// create parent directories if needed
if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
@@ -639,12 +631,12 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
return;
}
// create target file
- if ([[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil] == NO) {
+ if ([[NSFileManager defaultManager] createFileAtPath:self.target contents:nil attributes:nil] == NO) {
[self cancelTransferWithError:connection errorMessage:@"Could not create target file"];
return;
}
// open target file for writing
- self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
+ self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:self.target];
if (self.targetFileHandle == nil) {
[self cancelTransferWithError:connection errorMessage:@"Could not open target file for writing"];
}
[3/9] git commit: add ubuntu platform
Posted by st...@apache.org.
add ubuntu platform
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/4219ef3f
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/4219ef3f
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/4219ef3f
Branch: refs/heads/master
Commit: 4219ef3f81d542fad18d6c0716a2953614a381c4
Parents: 2d2e444
Author: Maxim Ermilov <ma...@canonical.com>
Authored: Wed Nov 13 09:54:59 2013 +0400
Committer: Maxim Ermilov <ma...@canonical.com>
Committed: Wed Nov 13 09:54:59 2013 +0400
----------------------------------------------------------------------
plugin.xml | 6 +
src/ubuntu/file-transfer.cpp | 247 ++++++++++++++++++++++++++++++++++++++
src/ubuntu/file-transfer.h | 97 +++++++++++++++
3 files changed, 350 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4219ef3f/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index deb8dae..c9a2019 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -35,6 +35,12 @@
<source-file src="src/android/FileUploadResult.java" target-dir="src/org/apache/cordova/filetransfer" />
</platform>
+ <!-- ubuntu -->
+ <platform name="ubuntu">
+ <header-file src="src/ubuntu/file-transfer.h" />
+ <source-file src="src/ubuntu/file-transfer.cpp" />
+ </platform>
+
<platform name="blackberry10">
<config-file target="www/config.xml" parent="/widget">
<feature name="FileTransfer" value="FileTransfer"></feature>
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4219ef3f/src/ubuntu/file-transfer.cpp
----------------------------------------------------------------------
diff --git a/src/ubuntu/file-transfer.cpp b/src/ubuntu/file-transfer.cpp
new file mode 100644
index 0000000..192ba98
--- /dev/null
+++ b/src/ubuntu/file-transfer.cpp
@@ -0,0 +1,247 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#include "file-transfer.h"
+#include <cassert>
+
+void FileTransfer::download(int scId, int ecId, const QString& url, const QString &target, bool /*trustAllHost*/, int id, const QVariantMap &/*headers*/) {
+ QSharedPointer<FileTransferRequest> request(new FileTransferRequest(_manager, scId, ecId, id, this));
+
+ assert(_id2request.find(id) == _id2request.end());
+
+ _id2request.insert(id, request);
+
+ request->connect(request.data(), &FileTransferRequest::done, [&]() {
+ auto it = _id2request.find(id);
+ while (it != _id2request.end() && it.key() == id) {
+ if (it.value().data() == request.data()) {
+ _id2request.erase(it);
+ break;
+ }
+ it++;
+ }
+ });
+ request->download(url, target);
+}
+
+void FileTransfer::upload(int scId, int ecId, const QString &filePath, const QString& url, const QString& fileKey, const QString& fileName, const QString& mimeType,
+ const QVariantMap & params, bool /*trustAllHosts*/, bool /*chunkedMode*/, const QVariantMap &headers, int id, const QString &httpMethod) {
+ QSharedPointer<FileTransferRequest> request(new FileTransferRequest(_manager, scId, ecId, id, this));
+
+ assert(_id2request.find(id) == _id2request.end());
+
+ _id2request.insert(id, request);
+
+ request->connect(request.data(), &FileTransferRequest::done, [&]() {
+ auto it = _id2request.find(id);
+ while (it != _id2request.end() && it.key() == id) {
+ if (it.value().data() == request.data()) {
+ _id2request.erase(it);
+ break;
+ }
+ it++;
+ }
+ });
+ request->upload(url, filePath, fileKey, fileName, mimeType, params, headers);
+}
+
+void FileTransfer::abort(int scId, int ecId, int id) {
+ Q_UNUSED(scId)
+ Q_UNUSED(ecId)
+
+ auto it = _id2request.find(id);
+ while (it != _id2request.end() && it.key() == id) {
+ (*it)->abort();
+ it++;
+ }
+}
+
+void FileTransferRequest::download(const QString& uri, const QString &target) {
+ QUrl url(uri);
+ QNetworkRequest request;
+
+ if (!url.isValid()) {
+ QVariantMap map;
+ map.insert("code", INVALID_URL_ERR);
+ map.insert("source", uri);
+ map.insert("target", target);
+ _plugin->cb(_ecId, map);
+ emit done();
+ return;
+ }
+
+ request.setUrl(url);
+ if (url.password().size() || url.userName().size()) {
+ QString headerData = "Basic " + (url.userName() + ":" + url.password()).toLocal8Bit().toBase64();
+ request.setRawHeader("Authorization", headerData.toLocal8Bit());
+ }
+ _reply = QSharedPointer<QNetworkReply>(_manager.get(request));
+
+ _reply->connect(_reply.data(), &QNetworkReply::finished, [this, target, uri]() {
+ if (!_scId || _reply->error() != QNetworkReply::NoError)
+ return;
+
+ QFile res(target);
+ qCritical() << target;
+ if (target[0] != '/' || !res.open(QIODevice::WriteOnly)) {
+ QVariantMap map;
+ map.insert("code", INVALID_URL_ERR);
+ map.insert("source", uri);
+ map.insert("target", target);
+ _plugin->cb(_ecId, map);
+ emit done();
+ return;
+ }
+ res.write(_reply->readAll());
+
+ QFileInfo info(target);
+ QVariantMap map;
+ map.insert("isFile", true);
+ map.insert("isDirectory", false);
+ map.insert("name", info.fileName());
+ map.insert("fullPath", info.absoluteFilePath());
+
+ _plugin->cb(_scId, map);
+
+ emit done();
+ });
+ _reply->connect(_reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
+ _reply->connect(_reply.data(), SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(progress(qint64, qint64)));
+}
+
+void FileTransferRequest::upload(const QString& _url, const QString& filePath, QString fileKey, QString fileName, QString mimeType, const QVariantMap ¶ms, const QVariantMap &headers) {
+ QUrl url(_url);
+ QNetworkRequest request;
+
+ if (!url.isValid()) {
+ QVariantMap map;
+ map.insert("code", INVALID_URL_ERR);
+ map.insert("source", filePath);
+ map.insert("target", _url);
+ _plugin->cb(_ecId, map);
+ emit done();
+ return;
+ }
+
+ QFile file(filePath);
+ if (filePath[0] != '/' || !file.open(QIODevice::ReadOnly)) {
+ QVariantMap map;
+ map.insert("code", FILE_NOT_FOUND_ERR);
+ map.insert("source", filePath);
+ map.insert("target", _url);
+ _plugin->cb(_ecId, map);
+ emit done();
+ return;
+ }
+ QString content{file.readAll()};
+
+ request.setUrl(url);
+ if (url.password().size() || url.userName().size()) {
+ QString headerData = "Basic " + (url.userName() + ":" + url.password()).toLocal8Bit().toBase64();
+ request.setRawHeader("Authorization", headerData.toLocal8Bit());
+ }
+
+ for (const QString &key: headers.keys()) {
+ const QString &value = headers.find(key)->toString();
+ request.setRawHeader(key.toUtf8(), value.toUtf8());
+ }
+
+ QString boundary = QString("CORDOVA-QT-%1A").arg(qrand());
+ while (content.contains(boundary)) {
+ boundary += QString("B%1A").arg(qrand());
+ }
+
+ request.setHeader(QNetworkRequest::ContentTypeHeader, QString("multipart/form-data; boundary=") + boundary);
+
+ fileKey.replace("\"", "");
+ fileName.replace("\"", "");
+ mimeType.replace("\"", "");
+ QString part = "--" + boundary + "\r\n";
+
+ part += "Content-Disposition: form-data; name=\"" + fileKey +"\"; filename=\"" + fileName + "\"\r\n";
+ part += "Content-Type: " + mimeType + "\r\n\r\n";
+ part += content + "\r\n";
+
+ for (QString key: params.keys()) {
+ part += "--" + boundary + "\r\n";
+ part += "Content-Disposition: form-data; name=\"" + key + "\";\r\n\r\n";
+ part += params.find(key)->toString();
+ part += "\r\n";
+ }
+
+ part += QString("--") + boundary + "--" + "\r\n";
+
+ _reply = QSharedPointer<QNetworkReply>(_manager.post(request, QByteArray(part.toUtf8())));
+
+ _reply->connect(_reply.data(), &QNetworkReply::finished, [this, content]() {
+ if (_reply->error() != QNetworkReply::NoError)
+ return;
+ int status = 200;
+ QVariant statusCode = _reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+
+ if (statusCode.isValid()) {
+ status = statusCode.toInt();
+ }
+
+ QVariantMap map;
+ map.insert("responseCode", status);
+ map.insert("response", QString(_reply->readAll()));
+ map.insert("bytesSent", content.size());
+ _plugin->cb(_scId, map);
+ emit done();
+ });
+ _reply->connect(_reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
+ _reply->connect(_reply.data(), SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(progress(qint64, qint64)));
+}
+
+void FileTransferRequest::abort() {
+ QVariantMap map;
+ map.insert("code", ABORT_ERR);
+ _plugin->cb(_ecId, map);
+ _scId = 0;
+ emit done();
+}
+
+void FileTransferRequest::error(QNetworkReply::NetworkError code) {
+ Q_UNUSED(code);
+
+ int status = 404;
+ QVariant statusCode = _reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+
+ if (statusCode.isValid()) {
+ status = statusCode.toInt();
+ }
+
+ QVariantMap map;
+ map.insert("http_status", status);
+ map.insert("body", QString(_reply->readAll()));
+ map.insert("code", CONNECTION_ERR);
+ _plugin->cb(_ecId, map);
+ emit done();
+}
+
+void FileTransferRequest::progress(qint64 bytesReceived, qint64 bytesTotal) {
+ QVariantMap map;
+ map.insert("lengthComputable", true);
+ map.insert("total", bytesTotal);
+ map.insert("loaded", bytesReceived);
+
+ if (bytesReceived && bytesTotal && _scId)
+ _plugin->callbackWithoutRemove(_scId, CordovaInternal::format(map));
+}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4219ef3f/src/ubuntu/file-transfer.h
----------------------------------------------------------------------
diff --git a/src/ubuntu/file-transfer.h b/src/ubuntu/file-transfer.h
new file mode 100644
index 0000000..b30a99f
--- /dev/null
+++ b/src/ubuntu/file-transfer.h
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#ifndef FILE_TRANSFER_H_SDASDASDAS
+#define FILE_TRANSFER_H_SDASDASDAS
+
+#include <QtCore>
+#include <QtNetwork>
+
+#include <cplugin.h>
+
+class FileTransferRequest: public QObject {
+ Q_OBJECT
+
+ QNetworkAccessManager &_manager;
+ int _scId, _ecId;
+ int _id;
+ QSharedPointer<QNetworkReply> _reply;
+
+ enum FileTransferError {
+ FILE_NOT_FOUND_ERR = 1,
+ INVALID_URL_ERR = 2,
+ CONNECTION_ERR = 3,
+ ABORT_ERR = 4
+ };
+
+public:
+ FileTransferRequest(QNetworkAccessManager &manager, int scId, int ecId, int id, CPlugin *plugin):
+ _manager(manager),
+ _scId(scId),
+ _ecId(ecId),
+ _id(id),
+ _plugin(plugin) {
+ }
+
+ void download(const QString& url, const QString &target);
+ void upload(const QString& _url, const QString& filePath, QString fileKey, QString fileName, QString mimeType, const QVariantMap ¶ms, const QVariantMap &headers);
+ void abort();
+
+signals:
+ void done();
+
+private slots:
+ void progress(qint64 bytesReceived, qint64 bytesTotal);
+ void error(QNetworkReply::NetworkError code);
+private:
+ CPlugin *_plugin;
+ Q_DISABLE_COPY(FileTransferRequest);
+};
+
+class FileTransfer : public CPlugin {
+ Q_OBJECT
+public:
+ explicit FileTransfer(Cordova *cordova): CPlugin(cordova) {
+ }
+
+ virtual const QString fullName() override {
+ return FileTransfer::fullID();
+ }
+
+ virtual const QString shortName() override {
+ return "FileTransfer";
+ }
+
+ static const QString fullID() {
+ return "FileTransfer";
+ }
+
+public slots:
+ void abort(int scId, int ecId, int id);
+ void download(int scId, int ecId, const QString& url, const QString &target, bool /*trustAllHost*/, int id, const QVariantMap &/*headers*/);
+ void upload(int scId, int ecId, const QString &filePath, const QString& url, const QString& fileKey, const QString& fileName, const QString& mimeType,
+ const QVariantMap & params, bool /*trustAllHosts*/, bool /*chunkedMode*/, const QVariantMap &headers, int id, const QString &httpMethod);
+
+private:
+ QNetworkAccessManager _manager;
+ QMultiMap<int, QSharedPointer<FileTransferRequest> > _id2request;
+ int lastRequestId;
+};
+
+#endif
[6/9] git commit: Merge branch 'dev' of
https://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer into dev
Posted by st...@apache.org.
Merge branch 'dev' of https://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer into dev
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/4c259e7a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/4c259e7a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/4c259e7a
Branch: refs/heads/master
Commit: 4c259e7a1488a49f9d889ec434e9608465339476
Parents: a80ae04 a61f0f3
Author: Steven Gill <st...@gmail.com>
Authored: Tue Nov 26 16:52:17 2013 -0800
Committer: Steven Gill <st...@gmail.com>
Committed: Tue Nov 26 16:52:17 2013 -0800
----------------------------------------------------------------------
plugin.xml | 2 +-
src/ios/CDVFileTransfer.h | 1 +
src/ios/CDVFileTransfer.m | 129 ++++++++++++++++++++++-------------------
www/FileTransfer.js | 1 +
4 files changed, 72 insertions(+), 61 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/4c259e7a/plugin.xml
----------------------------------------------------------------------
[9/9] git commit: [CB-5565] Updated version and RELEASENOTES.md for
release 0.4.0
Posted by st...@apache.org.
[CB-5565] Updated version and RELEASENOTES.md for release 0.4.0
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/76baae96
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/76baae96
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/76baae96
Branch: refs/heads/master
Commit: 76baae9690a1254a8b17cd36970597aabffac07e
Parents: 4c11f54
Author: Steven Gill <st...@gmail.com>
Authored: Wed Dec 4 15:16:30 2013 -0800
Committer: Steven Gill <st...@gmail.com>
Committed: Wed Dec 4 15:16:30 2013 -0800
----------------------------------------------------------------------
RELEASENOTES.md | 7 +++++++
plugin.xml | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/76baae96/RELEASENOTES.md
----------------------------------------------------------------------
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 5985831..2ef1bfd 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -37,3 +37,10 @@
### 0.3.4 (Oct 28, 2013)
* CB-5128: added repo + issue tag to plugin.xml for file transfer plugin
* [CB-5010] Incremented plugin version on dev branch.
+
+### 0.4.0 (Dec 4, 2013)
+* CB-5466: Partial revert; we're not ready yet for FS urls
+* add ubuntu platform
+* CB-5466: Minor version bump
+* CB-5466: Update FileTransfer plugin to accept filesystem urls
+* Added amazon-fireos platform. Change to use amazon-fireos as the platform if the user agen string contains 'cordova-amazon-fireos'
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/76baae96/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index 34371bb..91896f9 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.file-transfer"
- version="0.4.0-dev">
+ version="0.4.0">
<name>File Transfer</name>
<description>Cordova File Transfer Plugin</description>
<license>Apache 2.0</license>
[4/9] git commit: CB-5466: Update FileTransfer plugin to accept
filesystem urls
Posted by st...@apache.org.
CB-5466: Update FileTransfer plugin to accept filesystem urls
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/2f1411f5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/2f1411f5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/2f1411f5
Branch: refs/heads/master
Commit: 2f1411f5dc37854ded35ee31671e66b380b8117f
Parents: 60f96e0
Author: Ian Clelland <ic...@chromium.org>
Authored: Fri Nov 22 09:40:56 2013 -0500
Committer: Ian Clelland <ic...@chromium.org>
Committed: Fri Nov 22 10:31:38 2013 -0500
----------------------------------------------------------------------
src/ios/CDVFileTransfer.h | 1 +
src/ios/CDVFileTransfer.m | 129 ++++++++++++++++++++++-------------------
www/FileTransfer.js | 1 +
3 files changed, 71 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/2f1411f5/src/ios/CDVFileTransfer.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h
index 8e8211d..aa1cf9e 100644
--- a/src/ios/CDVFileTransfer.h
+++ b/src/ios/CDVFileTransfer.h
@@ -71,6 +71,7 @@ extern NSString* const kOptionsKeyCookie;
@property (nonatomic, copy) NSString* objectId;
@property (nonatomic, copy) NSString* source;
@property (nonatomic, copy) NSString* target;
+@property (nonatomic, copy) NSURL* targetURL;
@property (nonatomic, copy) NSString* mimeType;
@property (assign) int responseCode; // atomic
@property (nonatomic, assign) long long bytesTransfered;
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/2f1411f5/src/ios/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m
index f1fd4d3..2eec342 100644
--- a/src/ios/CDVFileTransfer.m
+++ b/src/ios/CDVFileTransfer.m
@@ -20,12 +20,15 @@
#import <Cordova/CDV.h>
#import "CDVFileTransfer.h"
#import "CDVFile.h"
+#import "CDVLocalFilesystem.h"
#import <AssetsLibrary/ALAsset.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
#import <AssetsLibrary/ALAssetsLibrary.h>
#import <CFNetwork/CFNetwork.h>
+extern CDVFile *filePlugin;
+
@interface CDVFileTransfer ()
// Sets the requests headers for the request.
- (void)applyRequestHeaders:(NSDictionary*)headers toRequest:(NSMutableURLRequest*)req;
@@ -270,52 +273,48 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
- (void)fileDataForUploadCommand:(CDVInvokedUrlCommand*)command
{
- NSString* target = (NSString*)[command.arguments objectAtIndex:0];
+ NSString* source = (NSString*)[command.arguments objectAtIndex:0];
+ NSString* server = [command.arguments objectAtIndex:1];
NSError* __autoreleasing err = nil;
- // return unsupported result for assets-library URLs
- if ([target hasPrefix:kCDVAssetsLibraryPrefix]) {
- // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
- ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
- if (asset) {
- // We have the asset! Get the data and send it off.
- ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
- Byte* buffer = (Byte*)malloc([assetRepresentation size]);
- NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil];
- NSData* fileData = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
- [self uploadData:fileData command:command];
- } else {
+ CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:source];
+ NSObject<CDVFileSystem> *fs;
+ if (sourceURL) {
+ // Try to get a CDVFileSystem which will handle this file.
+ // This requires talking to the current CDVFile plugin.
+ fs = [filePlugin filesystemForURL:sourceURL];
+ }
+ if (fs) {
+ [fs readFileAtURL:sourceURL start:0 end:-1 callback:^(NSData *fileData, NSString *mimeType, CDVFileError err) {
+ if (err) {
// We couldn't find the asset. Send the appropriate error.
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ } else {
+ [self uploadData:fileData command:command];
}
- };
- ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
- // Retrieving the asset failed for some reason. Send the appropriate error.
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- };
-
- ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
- [assetsLibrary assetForURL:[NSURL URLWithString:target] resultBlock:resultBlock failureBlock:failureBlock];
+ }];
return;
} else {
// Extract the path part out of a file: URL.
- NSString* filePath = [target hasPrefix:@"/"] ? [target copy] : [[NSURL URLWithString:target] path];
+ NSString* filePath = [source hasPrefix:@"/"] ? [source copy] : [[NSURL URLWithString:source] path];
if (filePath == nil) {
// We couldn't find the asset. Send the appropriate error.
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
return;
}
-
+
// Memory map the file so that it can be read efficiently even if it is large.
NSData* fileData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&err];
-
+
if (err != nil) {
- NSLog(@"Error opening file %@: %@", target, err);
+ NSLog(@"Error opening file %@: %@", source, err);
+ CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
+ [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+ } else {
+ [self uploadData:fileData command:command];
}
- [self uploadData:fileData command:command];
}
}
@@ -359,47 +358,43 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
- (void)download:(CDVInvokedUrlCommand*)command
{
DLog(@"File Transfer downloading file...");
- NSString* sourceUrl = [command.arguments objectAtIndex:0];
- NSString* filePath = [command.arguments objectAtIndex:1];
+ NSString* source = [command.arguments objectAtIndex:0];
+ NSString* target = [command.arguments objectAtIndex:1];
BOOL trustAllHosts = [[command.arguments objectAtIndex:2 withDefault:[NSNumber numberWithBool:YES]] boolValue]; // allow self-signed certs
NSString* objectId = [command.arguments objectAtIndex:3];
NSDictionary* headers = [command.arguments objectAtIndex:4 withDefault:nil];
- // return unsupported result for assets-library URLs
- if ([filePath hasPrefix:kCDVAssetsLibraryPrefix]) {
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"download not supported for assets-library URLs."];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- return;
- }
-
CDVPluginResult* result = nil;
CDVFileTransferError errorCode = 0;
- NSURL* file;
+ NSURL* targetURL;
- if ([filePath hasPrefix:@"/"]) {
- file = [NSURL fileURLWithPath:filePath];
+ if ([target hasPrefix:@"/"]) {
+ targetURL = [NSURL fileURLWithPath:target];
} else {
- file = [NSURL URLWithString:filePath];
+ targetURL = [NSURL URLWithString:target];
}
- NSURL* url = [NSURL URLWithString:sourceUrl];
+ NSURL* sourceURL = [NSURL URLWithString:source];
- if (!url) {
+ if (!sourceURL) {
errorCode = INVALID_URL_ERR;
- NSLog(@"File Transfer Error: Invalid server URL %@", sourceUrl);
- } else if (![file isFileURL]) {
- errorCode = FILE_NOT_FOUND_ERR;
- NSLog(@"File Transfer Error: Invalid file path or URL %@", filePath);
+ NSLog(@"File Transfer Error: Invalid server URL %@", source);
+ } else if (![targetURL isFileURL]) {
+ CDVFilesystemURL *fsURL = [CDVFilesystemURL fileSystemURLWithString:target];
+ if (!fsURL) {
+ errorCode = FILE_NOT_FOUND_ERR;
+ NSLog(@"File Transfer Error: Invalid file path or URL %@", target);
+ }
}
if (errorCode > 0) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:errorCode AndSource:sourceUrl AndTarget:filePath]];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:errorCode AndSource:source AndTarget:target]];
[self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
return;
}
- NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
+ NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:sourceURL];
[self applyRequestHeaders:headers toRequest:req];
CDVFileTransferDelegate* delegate = [[CDVFileTransferDelegate alloc] init];
@@ -407,8 +402,9 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
delegate.direction = CDV_TRANSFER_DOWNLOAD;
delegate.callbackId = command.callbackId;
delegate.objectId = objectId;
- delegate.source = sourceUrl;
- delegate.target = filePath;
+ delegate.source = source;
+ delegate.target = target;
+ delegate.targetURL = targetURL;
delegate.trustAllHosts = trustAllHosts;
delegate.connection = [NSURLConnection connectionWithRequest:req delegate:delegate];
@@ -521,8 +517,6 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
NSString* downloadResponse = nil;
NSMutableDictionary* uploadResult;
CDVPluginResult* result = nil;
- BOOL bDirRequest = NO;
- CDVFile* file;
NSLog(@"File Transfer Finished with response code %d", self.responseCode);
@@ -548,8 +542,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
self.targetFileHandle = nil;
DLog(@"File Transfer Download success");
- file = [[CDVFile alloc] init];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[file getDirectoryEntry:target isDirectory:bDirRequest]];
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin makeEntryForURL:self.targetURL]];
} else {
downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[command createFileTransferError:CONNECTION_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]];
@@ -618,7 +611,23 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
}
if ((self.direction == CDV_TRANSFER_DOWNLOAD) && (self.responseCode >= 200) && (self.responseCode < 300)) {
// Download response is okay; begin streaming output to file
- NSString* parentPath = [self.target stringByDeletingLastPathComponent];
+ NSString *filePath = nil;
+ CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:self.target];
+ if (sourceURL && sourceURL.fileSystemType != -1) {
+ // This requires talking to the current CDVFile plugin
+ NSObject<CDVFileSystem> *fs = [filePlugin.fileSystems objectAtIndex:sourceURL.fileSystemType];
+ filePath = [fs filesystemPathForURL:sourceURL];
+ } else {
+ // Extract the path part out of a file: URL.
+ NSString* filePath = [self.target hasPrefix:@"/"] ? [self.target copy] : [[NSURL URLWithString:self.target] path];
+ if (filePath == nil) {
+ // We couldn't find the asset. Send the appropriate error.
+ [self cancelTransferWithError:connection errorMessage:[NSString stringWithFormat:@"Could not create target file"]];
+ return;
+ }
+ }
+
+ NSString* parentPath = [filePath stringByDeletingLastPathComponent];
// create parent directories if needed
if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
@@ -630,16 +639,16 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
return;
}
// create target file
- if ([[NSFileManager defaultManager] createFileAtPath:self.target contents:nil attributes:nil] == NO) {
+ if ([[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil] == NO) {
[self cancelTransferWithError:connection errorMessage:@"Could not create target file"];
return;
}
// open target file for writing
- self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:self.target];
+ self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
if (self.targetFileHandle == nil) {
[self cancelTransferWithError:connection errorMessage:@"Could not open target file for writing"];
}
- DLog(@"Streaming to file %@", target);
+ DLog(@"Streaming to file %@", filePath);
}
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/2f1411f5/www/FileTransfer.js
----------------------------------------------------------------------
diff --git a/www/FileTransfer.js b/www/FileTransfer.js
index 66a1c4b..d6690fe 100644
--- a/www/FileTransfer.js
+++ b/www/FileTransfer.js
@@ -184,6 +184,7 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro
entry.isFile = result.isFile;
entry.name = result.name;
entry.fullPath = result.fullPath;
+ entry.filesystem = new FileSystem(result.filesystem == window.PERSISTENT ? 'persistent' : 'temporary');
successCallback(entry);
}
};
[2/9] git commit: Added amazon-fireos platform. Change to use
amazon-fireos as the platform if the user agen string contains
'cordova-amazon-fireos'
Posted by st...@apache.org.
Added amazon-fireos platform.
Change to use amazon-fireos as the platform if the user agen string contains 'cordova-amazon-fireos'
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/a80ae041
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/a80ae041
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/a80ae041
Branch: refs/heads/master
Commit: a80ae0417b45052c8e2064f605c7027afcadcd06
Parents: 60f96e0
Author: Archana Naik <na...@lab126.com>
Authored: Fri Oct 18 14:44:05 2013 -0700
Committer: Archana Naik <na...@lab126.com>
Committed: Wed Oct 30 13:20:08 2013 -0700
----------------------------------------------------------------------
plugin.xml | 17 +
src/amazon/FileTransfer.java | 873 ++++++++++++++++++++++++++++++++++++++
test/cordova-incl.js | 3 +-
3 files changed, 892 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/a80ae041/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index d1de8dd..8d6bafe 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -37,6 +37,23 @@
<source-file src="src/android/FileUploadResult.java" target-dir="src/org/apache/cordova/filetransfer" />
</platform>
+ <!-- amamzon-fireos -->
+ <platform name="amazon-fireos">
+ <config-file target="res/xml/config.xml" parent="/*">
+ <feature name="FileTransfer" >
+ <param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer"/>
+ </feature>
+ </config-file>
+
+ <config-file target="AndroidManifest.xml" parent="/*">
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ </config-file>
+
+ <source-file src="src/amazon/FileTransfer.java" target-dir="src/org/apache/cordova/filetransfer" />
+ <source-file src="src/android/FileProgressResult.java" target-dir="src/org/apache/cordova/filetransfer" />
+ <source-file src="src/android/FileUploadResult.java" target-dir="src/org/apache/cordova/filetransfer" />
+ </platform>
+
<platform name="blackberry10">
<config-file target="www/config.xml" parent="/widget">
<feature name="FileTransfer" value="FileTransfer"></feature>
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/a80ae041/src/amazon/FileTransfer.java
----------------------------------------------------------------------
diff --git a/src/amazon/FileTransfer.java b/src/amazon/FileTransfer.java
new file mode 100644
index 0000000..2e0c31c
--- /dev/null
+++ b/src/amazon/FileTransfer.java
@@ -0,0 +1,873 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+package org.apache.cordova.filetransfer;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.Inflater;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.cordova.Config;
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaResourceApi;
+import org.apache.cordova.CordovaResourceApi.OpenForReadResult;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.file.FileUtils;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.net.Uri;
+import android.os.Build;
+import android.util.Log;
+import com.amazon.android.webkit.AmazonCookieManager;
+
+public class FileTransfer extends CordovaPlugin {
+
+ private static final String LOG_TAG = "FileTransfer";
+ private static final String LINE_START = "--";
+ private static final String LINE_END = "\r\n";
+ private static final String BOUNDARY = "+++++";
+
+ public static int FILE_NOT_FOUND_ERR = 1;
+ public static int INVALID_URL_ERR = 2;
+ public static int CONNECTION_ERR = 3;
+ public static int ABORTED_ERR = 4;
+
+ private static HashMap<String, RequestContext> activeRequests = new HashMap<String, RequestContext>();
+ private static final int MAX_BUFFER_SIZE = 16 * 1024;
+
+ private static final class RequestContext {
+ String source;
+ String target;
+ File targetFile;
+ CallbackContext callbackContext;
+ InputStream currentInputStream;
+ OutputStream currentOutputStream;
+ boolean aborted;
+ RequestContext(String source, String target, CallbackContext callbackContext) {
+ this.source = source;
+ this.target = target;
+ this.callbackContext = callbackContext;
+ }
+ void sendPluginResult(PluginResult pluginResult) {
+ synchronized (this) {
+ if (!aborted) {
+ callbackContext.sendPluginResult(pluginResult);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds an interface method to an InputStream to return the number of bytes
+ * read from the raw stream. This is used to track total progress against
+ * the HTTP Content-Length header value from the server.
+ */
+ private static abstract class TrackingInputStream extends FilterInputStream {
+ public TrackingInputStream(final InputStream in) {
+ super(in);
+ }
+ public abstract long getTotalRawBytesRead();
+ }
+
+ private static class ExposedGZIPInputStream extends GZIPInputStream {
+ public ExposedGZIPInputStream(final InputStream in) throws IOException {
+ super(in);
+ }
+ public Inflater getInflater() {
+ return inf;
+ }
+ }
+
+ /**
+ * Provides raw bytes-read tracking for a GZIP input stream. Reports the
+ * total number of compressed bytes read from the input, rather than the
+ * number of uncompressed bytes.
+ */
+ private static class TrackingGZIPInputStream extends TrackingInputStream {
+ private ExposedGZIPInputStream gzin;
+ public TrackingGZIPInputStream(final ExposedGZIPInputStream gzin) throws IOException {
+ super(gzin);
+ this.gzin = gzin;
+ }
+ public long getTotalRawBytesRead() {
+ return gzin.getInflater().getBytesRead();
+ }
+ }
+
+ /**
+ * Provides simple total-bytes-read tracking for an existing InputStream
+ */
+ private static class SimpleTrackingInputStream extends TrackingInputStream {
+ private long bytesRead = 0;
+ public SimpleTrackingInputStream(InputStream stream) {
+ super(stream);
+ }
+
+ private int updateBytesRead(int newBytesRead) {
+ if (newBytesRead != -1) {
+ bytesRead += newBytesRead;
+ }
+ return newBytesRead;
+ }
+
+ @Override
+ public int read() throws IOException {
+ return updateBytesRead(super.read());
+ }
+
+ @Override
+ public int read(byte[] buffer) throws IOException {
+ return updateBytesRead(super.read(buffer));
+ }
+
+ @Override
+ public int read(byte[] bytes, int offset, int count) throws IOException {
+ return updateBytesRead(super.read(bytes, offset, count));
+ }
+
+ public long getTotalRawBytesRead() {
+ return bytesRead;
+ }
+ }
+
+ @Override
+ public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
+ if (action.equals("upload") || action.equals("download")) {
+ String source = args.getString(0);
+ String target = args.getString(1);
+
+ if (action.equals("upload")) {
+ try {
+ source = URLDecoder.decode(source, "UTF-8");
+ upload(source, target, args, callbackContext);
+ } catch (UnsupportedEncodingException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.MALFORMED_URL_EXCEPTION, "UTF-8 error."));
+ }
+ } else {
+ download(source, target, args, callbackContext);
+ }
+ return true;
+ } else if (action.equals("abort")) {
+ String objectId = args.getString(0);
+ abort(objectId);
+ callbackContext.success();
+ return true;
+ }
+ return false;
+ }
+
+ private static void addHeadersToRequest(URLConnection connection, JSONObject headers) {
+ try {
+ for (Iterator<?> iter = headers.keys(); iter.hasNext(); ) {
+ String headerKey = iter.next().toString();
+ JSONArray headerValues = headers.optJSONArray(headerKey);
+ if (headerValues == null) {
+ headerValues = new JSONArray();
+ headerValues.put(headers.getString(headerKey));
+ }
+ connection.setRequestProperty(headerKey, headerValues.getString(0));
+ for (int i = 1; i < headerValues.length(); ++i) {
+ connection.addRequestProperty(headerKey, headerValues.getString(i));
+ }
+ }
+ } catch (JSONException e1) {
+ // No headers to be manipulated!
+ }
+ }
+
+ /**
+ * Uploads the specified file to the server URL provided using an HTTP multipart request.
+ * @param source Full path of the file on the file system
+ * @param target URL of the server to receive the file
+ * @param args JSON Array of args
+ * @param callbackContext callback id for optional progress reports
+ *
+ * args[2] fileKey Name of file request parameter
+ * args[3] fileName File name to be used on server
+ * args[4] mimeType Describes file content type
+ * args[5] params key:value pairs of user-defined parameters
+ * @return FileUploadResult containing result of upload request
+ */
+ private void upload(final String source, final String target, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ Log.d(LOG_TAG, "upload " + source + " to " + target);
+
+ // Setup the options
+ final String fileKey = getArgument(args, 2, "file");
+ final String fileName = getArgument(args, 3, "image.jpg");
+ final String mimeType = getArgument(args, 4, "image/jpeg");
+ final JSONObject params = args.optJSONObject(5) == null ? new JSONObject() : args.optJSONObject(5);
+ final boolean trustEveryone = args.optBoolean(6);
+ // Always use chunked mode unless set to false as per API
+ final boolean chunkedMode = args.optBoolean(7) || args.isNull(7);
+ // Look for headers on the params map for backwards compatibility with older Cordova versions.
+ final JSONObject headers = args.optJSONObject(8) == null ? params.optJSONObject("headers") : args.optJSONObject(8);
+ final String objectId = args.getString(9);
+ final String httpMethod = getArgument(args, 10, "POST");
+
+ final CordovaResourceApi resourceApi = webView.getResourceApi();
+
+ Log.d(LOG_TAG, "fileKey: " + fileKey);
+ Log.d(LOG_TAG, "fileName: " + fileName);
+ Log.d(LOG_TAG, "mimeType: " + mimeType);
+ Log.d(LOG_TAG, "params: " + params);
+ Log.d(LOG_TAG, "trustEveryone: " + trustEveryone);
+ Log.d(LOG_TAG, "chunkedMode: " + chunkedMode);
+ Log.d(LOG_TAG, "headers: " + headers);
+ Log.d(LOG_TAG, "objectId: " + objectId);
+ Log.d(LOG_TAG, "httpMethod: " + httpMethod);
+
+ final Uri targetUri = resourceApi.remapUri(Uri.parse(target));
+ // Accept a path or a URI for the source.
+ Uri tmpSrc = Uri.parse(source);
+ final Uri sourceUri = resourceApi.remapUri(
+ tmpSrc.getScheme() != null ? tmpSrc : Uri.fromFile(new File(source)));
+
+ int uriType = CordovaResourceApi.getUriType(targetUri);
+ final boolean useHttps = uriType == CordovaResourceApi.URI_TYPE_HTTPS;
+ if (uriType != CordovaResourceApi.URI_TYPE_HTTP && !useHttps) {
+ JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0);
+ Log.e(LOG_TAG, "Unsupported URI: " + targetUri);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ return;
+ }
+
+ final RequestContext context = new RequestContext(source, target, callbackContext);
+ synchronized (activeRequests) {
+ activeRequests.put(objectId, context);
+ }
+
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ if (context.aborted) {
+ return;
+ }
+ HttpURLConnection conn = null;
+ HostnameVerifier oldHostnameVerifier = null;
+ SSLSocketFactory oldSocketFactory = null;
+ int totalBytes = 0;
+ int fixedLength = -1;
+ try {
+ // Create return object
+ FileUploadResult result = new FileUploadResult();
+ FileProgressResult progress = new FileProgressResult();
+
+ //------------------ CLIENT REQUEST
+ // Open a HTTP connection to the URL based on protocol
+ conn = resourceApi.createHttpConnection(targetUri);
+ if (useHttps && trustEveryone) {
+ // Setup the HTTPS connection class to trust everyone
+ HttpsURLConnection https = (HttpsURLConnection)conn;
+ oldSocketFactory = trustAllHosts(https);
+ // Save the current hostnameVerifier
+ oldHostnameVerifier = https.getHostnameVerifier();
+ // Setup the connection not to verify hostnames
+ https.setHostnameVerifier(DO_NOT_VERIFY);
+ }
+
+ // Allow Inputs
+ conn.setDoInput(true);
+
+ // Allow Outputs
+ conn.setDoOutput(true);
+
+ // Don't use a cached copy.
+ conn.setUseCaches(false);
+
+ // Use a post method.
+ conn.setRequestMethod(httpMethod);
+ conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
+
+ // Set the cookies on the response
+ String cookie = AmazonCookieManager.getInstance().getCookie(target);
+ if (cookie != null) {
+ conn.setRequestProperty("Cookie", cookie);
+ }
+
+ // Handle the other headers
+ if (headers != null) {
+ addHeadersToRequest(conn, headers);
+ }
+
+ /*
+ * Store the non-file portions of the multipart data as a string, so that we can add it
+ * to the contentSize, since it is part of the body of the HTTP request.
+ */
+ StringBuilder beforeData = new StringBuilder();
+ try {
+ for (Iterator<?> iter = params.keys(); iter.hasNext();) {
+ Object key = iter.next();
+ if(!String.valueOf(key).equals("headers"))
+ {
+ beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
+ beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append('"');
+ beforeData.append(LINE_END).append(LINE_END);
+ beforeData.append(params.getString(key.toString()));
+ beforeData.append(LINE_END);
+ }
+ }
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+
+ beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
+ beforeData.append("Content-Disposition: form-data; name=\"").append(fileKey).append("\";");
+ beforeData.append(" filename=\"").append(fileName).append('"').append(LINE_END);
+ beforeData.append("Content-Type: ").append(mimeType).append(LINE_END).append(LINE_END);
+ byte[] beforeDataBytes = beforeData.toString().getBytes("UTF-8");
+ byte[] tailParamsBytes = (LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END).getBytes("UTF-8");
+
+
+ // Get a input stream of the file on the phone
+ OpenForReadResult readResult = resourceApi.openForRead(sourceUri);
+
+ int stringLength = beforeDataBytes.length + tailParamsBytes.length;
+ if (readResult.length >= 0) {
+ fixedLength = (int)readResult.length + stringLength;
+ progress.setLengthComputable(true);
+ progress.setTotal(fixedLength);
+ }
+ Log.d(LOG_TAG, "Content Length: " + fixedLength);
+ // setFixedLengthStreamingMode causes and OutOfMemoryException on pre-Froyo devices.
+ // http://code.google.com/p/android/issues/detail?id=3164
+ // It also causes OOM if HTTPS is used, even on newer devices.
+ boolean useChunkedMode = chunkedMode && (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO || useHttps);
+ useChunkedMode = useChunkedMode || (fixedLength == -1);
+
+ if (useChunkedMode) {
+ conn.setChunkedStreamingMode(MAX_BUFFER_SIZE);
+ // Although setChunkedStreamingMode sets this header, setting it explicitly here works
+ // around an OutOfMemoryException when using https.
+ conn.setRequestProperty("Transfer-Encoding", "chunked");
+ } else {
+ conn.setFixedLengthStreamingMode(fixedLength);
+ }
+
+ conn.connect();
+
+ OutputStream sendStream = null;
+ try {
+ sendStream = conn.getOutputStream();
+ synchronized (context) {
+ if (context.aborted) {
+ return;
+ }
+ context.currentOutputStream = sendStream;
+ }
+ //We don't want to change encoding, we just want this to write for all Unicode.
+ sendStream.write(beforeDataBytes);
+ totalBytes += beforeDataBytes.length;
+
+ // create a buffer of maximum size
+ int bytesAvailable = readResult.inputStream.available();
+ int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
+ byte[] buffer = new byte[bufferSize];
+
+ // read file and write it into form...
+ int bytesRead = readResult.inputStream.read(buffer, 0, bufferSize);
+
+ long prevBytesRead = 0;
+ while (bytesRead > 0) {
+ result.setBytesSent(totalBytes);
+ sendStream.write(buffer, 0, bytesRead);
+ totalBytes += bytesRead;
+ if (totalBytes > prevBytesRead + 102400) {
+ prevBytesRead = totalBytes;
+ Log.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
+ }
+ bytesAvailable = readResult.inputStream.available();
+ bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
+ bytesRead = readResult.inputStream.read(buffer, 0, bufferSize);
+
+ // Send a progress event.
+ progress.setLoaded(totalBytes);
+ PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
+ progressResult.setKeepCallback(true);
+ context.sendPluginResult(progressResult);
+ }
+
+ // send multipart form data necessary after file data...
+ sendStream.write(tailParamsBytes);
+ totalBytes += tailParamsBytes.length;
+ sendStream.flush();
+ } finally {
+ safeClose(readResult.inputStream);
+ safeClose(sendStream);
+ }
+ context.currentOutputStream = null;
+ Log.d(LOG_TAG, "Sent " + totalBytes + " of " + fixedLength);
+
+ //------------------ read the SERVER RESPONSE
+ String responseString;
+ int responseCode = conn.getResponseCode();
+ Log.d(LOG_TAG, "response code: " + responseCode);
+ Log.d(LOG_TAG, "response headers: " + conn.getHeaderFields());
+ TrackingInputStream inStream = null;
+ try {
+ inStream = getInputStream(conn);
+ synchronized (context) {
+ if (context.aborted) {
+ return;
+ }
+ context.currentInputStream = inStream;
+ }
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(1024, conn.getContentLength()));
+ byte[] buffer = new byte[1024];
+ int bytesRead = 0;
+ // write bytes to file
+ while ((bytesRead = inStream.read(buffer)) > 0) {
+ out.write(buffer, 0, bytesRead);
+ }
+ responseString = out.toString("UTF-8");
+ } finally {
+ context.currentInputStream = null;
+ safeClose(inStream);
+ }
+
+ Log.d(LOG_TAG, "got response from server");
+ Log.d(LOG_TAG, responseString.substring(0, Math.min(256, responseString.length())));
+
+ // send request and retrieve response
+ result.setResponseCode(responseCode);
+ result.setResponse(responseString);
+
+ context.sendPluginResult(new PluginResult(PluginResult.Status.OK, result.toJSONObject()));
+ } catch (FileNotFoundException e) {
+ JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, conn);
+ Log.e(LOG_TAG, error.toString(), e);
+ context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ } catch (IOException e) {
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
+ Log.e(LOG_TAG, error.toString(), e);
+ Log.e(LOG_TAG, "Failed after uploading " + totalBytes + " of " + fixedLength + " bytes.");
+ context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ context.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ } catch (Throwable t) {
+ // Shouldn't happen, but will
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
+ Log.e(LOG_TAG, error.toString(), t);
+ context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ } finally {
+ synchronized (activeRequests) {
+ activeRequests.remove(objectId);
+ }
+
+ if (conn != null) {
+ // Revert back to the proper verifier and socket factories
+ // Revert back to the proper verifier and socket factories
+ if (trustEveryone && useHttps) {
+ HttpsURLConnection https = (HttpsURLConnection) conn;
+ https.setHostnameVerifier(oldHostnameVerifier);
+ https.setSSLSocketFactory(oldSocketFactory);
+ }
+ }
+ }
+ }
+ });
+ }
+
+ private static void safeClose(Closeable stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private static TrackingInputStream getInputStream(URLConnection conn) throws IOException {
+ String encoding = conn.getContentEncoding();
+ if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
+ return new TrackingGZIPInputStream(new ExposedGZIPInputStream(conn.getInputStream()));
+ }
+ return new SimpleTrackingInputStream(conn.getInputStream());
+ }
+
+ // always verify the host - don't check for certificate
+ private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ };
+ // Create a trust manager that does not validate certificate chains
+ private static final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return new java.security.cert.X509Certificate[] {};
+ }
+
+ public void checkClientTrusted(X509Certificate[] chain,
+ String authType) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain,
+ String authType) throws CertificateException {
+ }
+ } };
+
+ /**
+ * This function will install a trust manager that will blindly trust all SSL
+ * certificates. The reason this code is being added is to enable developers
+ * to do development using self signed SSL certificates on their web server.
+ *
+ * The standard HttpsURLConnection class will throw an exception on self
+ * signed certificates if this code is not run.
+ */
+ private static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) {
+ // Install the all-trusting trust manager
+ SSLSocketFactory oldFactory = connection.getSSLSocketFactory();
+ try {
+ // Install our all trusting manager
+ SSLContext sc = SSLContext.getInstance("TLS");
+ sc.init(null, trustAllCerts, new java.security.SecureRandom());
+ SSLSocketFactory newFactory = sc.getSocketFactory();
+ connection.setSSLSocketFactory(newFactory);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ return oldFactory;
+ }
+
+ private static JSONObject createFileTransferError(int errorCode, String source, String target, URLConnection connection) {
+
+ int httpStatus = 0;
+ StringBuilder bodyBuilder = new StringBuilder();
+ String body = null;
+ if (connection != null) {
+ try {
+ if (connection instanceof HttpURLConnection) {
+ httpStatus = ((HttpURLConnection)connection).getResponseCode();
+ InputStream err = ((HttpURLConnection) connection).getErrorStream();
+ if(err != null)
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(err, "UTF-8"));
+ String line = reader.readLine();
+ while(line != null)
+ {
+ bodyBuilder.append(line);
+ line = reader.readLine();
+ if(line != null)
+ bodyBuilder.append('\n');
+ }
+ body = bodyBuilder.toString();
+ }
+ }
+ // IOException can leave connection object in a bad state, so catch all exceptions.
+ } catch (Throwable e) {
+ Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
+ }
+ }
+
+ return createFileTransferError(errorCode, source, target, body, httpStatus);
+ }
+
+ /**
+ * Create an error object based on the passed in errorCode
+ * @param errorCode the error
+ * @return JSONObject containing the error
+ */
+ private static JSONObject createFileTransferError(int errorCode, String source, String target, String body, Integer httpStatus) {
+ JSONObject error = null;
+ try {
+ error = new JSONObject();
+ error.put("code", errorCode);
+ error.put("source", source);
+ error.put("target", target);
+ if(body != null)
+ {
+ error.put("body", body);
+ }
+ if (httpStatus != null) {
+ error.put("http_status", httpStatus);
+ }
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ return error;
+ }
+
+ /**
+ * Convenience method to read a parameter from the list of JSON args.
+ * @param args the args passed to the Plugin
+ * @param position the position to retrieve the arg from
+ * @param defaultString the default to be used if the arg does not exist
+ * @return String with the retrieved value
+ */
+ private static String getArgument(JSONArray args, int position, String defaultString) {
+ String arg = defaultString;
+ if (args.length() > position) {
+ arg = args.optString(position);
+ if (arg == null || "null".equals(arg)) {
+ arg = defaultString;
+ }
+ }
+ return arg;
+ }
+
+ /**
+ * Downloads a file form a given URL and saves it to the specified directory.
+ *
+ * @param source URL of the server to receive the file
+ * @param target Full path of the file on the file system
+ */
+ private void download(final String source, final String target, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ Log.d(LOG_TAG, "download " + source + " to " + target);
+
+ final CordovaResourceApi resourceApi = webView.getResourceApi();
+
+ final boolean trustEveryone = args.optBoolean(2);
+ final String objectId = args.getString(3);
+ final JSONObject headers = args.optJSONObject(4);
+
+ final Uri sourceUri = resourceApi.remapUri(Uri.parse(source));
+ // Accept a path or a URI for the source.
+ Uri tmpTarget = Uri.parse(target);
+ final Uri targetUri = resourceApi.remapUri(
+ tmpTarget.getScheme() != null ? tmpTarget : Uri.fromFile(new File(target)));
+
+ int uriType = CordovaResourceApi.getUriType(sourceUri);
+ final boolean useHttps = uriType == CordovaResourceApi.URI_TYPE_HTTPS;
+ final boolean isLocalTransfer = !useHttps && uriType != CordovaResourceApi.URI_TYPE_HTTP;
+ if (uriType == CordovaResourceApi.URI_TYPE_UNKNOWN) {
+ JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0);
+ Log.e(LOG_TAG, "Unsupported URI: " + targetUri);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ return;
+ }
+
+ // TODO: refactor to also allow resources & content:
+ if (!isLocalTransfer && !Config.isUrlWhiteListed(source)) {
+ Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, null, 401);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
+ return;
+ }
+
+
+ final RequestContext context = new RequestContext(source, target, callbackContext);
+ synchronized (activeRequests) {
+ activeRequests.put(objectId, context);
+ }
+
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ if (context.aborted) {
+ return;
+ }
+ HttpURLConnection connection = null;
+ HostnameVerifier oldHostnameVerifier = null;
+ SSLSocketFactory oldSocketFactory = null;
+ File file = null;
+ PluginResult result = null;
+ TrackingInputStream inputStream = null;
+
+ OutputStream outputStream = null;
+ try {
+ OpenForReadResult readResult = null;
+ outputStream = resourceApi.openOutputStream(targetUri);
+
+ file = resourceApi.mapUriToFile(targetUri);
+ context.targetFile = file;
+
+ Log.d(LOG_TAG, "Download file:" + sourceUri);
+
+ FileProgressResult progress = new FileProgressResult();
+
+ if (isLocalTransfer) {
+ readResult = resourceApi.openForRead(sourceUri);
+ if (readResult.length != -1) {
+ progress.setLengthComputable(true);
+ progress.setTotal(readResult.length);
+ }
+ inputStream = new SimpleTrackingInputStream(readResult.inputStream);
+ } else {
+ // connect to server
+ // Open a HTTP connection to the URL based on protocol
+ connection = resourceApi.createHttpConnection(sourceUri);
+ if (useHttps && trustEveryone) {
+ // Setup the HTTPS connection class to trust everyone
+ HttpsURLConnection https = (HttpsURLConnection)connection;
+ oldSocketFactory = trustAllHosts(https);
+ // Save the current hostnameVerifier
+ oldHostnameVerifier = https.getHostnameVerifier();
+ // Setup the connection not to verify hostnames
+ https.setHostnameVerifier(DO_NOT_VERIFY);
+ }
+
+ connection.setRequestMethod("GET");
+
+ // TODO: Make OkHttp use this AmazonCookieManager by default.
+ String cookie = AmazonCookieManager.getInstance().getCookie(sourceUri.toString());
+ if(cookie != null)
+ {
+ connection.setRequestProperty("cookie", cookie);
+ }
+
+ // This must be explicitly set for gzip progress tracking to work.
+ connection.setRequestProperty("Accept-Encoding", "gzip");
+
+ // Handle the other headers
+ if (headers != null) {
+ addHeadersToRequest(connection, headers);
+ }
+
+ connection.connect();
+
+ if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) {
+ // Only trust content-length header if we understand
+ // the encoding -- identity or gzip
+ progress.setLengthComputable(true);
+ progress.setTotal(connection.getContentLength());
+ }
+ inputStream = getInputStream(connection);
+ }
+
+ try {
+ synchronized (context) {
+ if (context.aborted) {
+ return;
+ }
+ context.currentInputStream = inputStream;
+ }
+
+ // write bytes to file
+ byte[] buffer = new byte[MAX_BUFFER_SIZE];
+ int bytesRead = 0;
+ while ((bytesRead = inputStream.read(buffer)) > 0) {
+ outputStream.write(buffer, 0, bytesRead);
+ // Send a progress event.
+ progress.setLoaded(inputStream.getTotalRawBytesRead());
+ PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
+ progressResult.setKeepCallback(true);
+ context.sendPluginResult(progressResult);
+ }
+ } finally {
+ context.currentInputStream = null;
+ safeClose(inputStream);
+ safeClose(outputStream);
+ }
+
+ Log.d(LOG_TAG, "Saved file: " + target);
+
+ // create FileEntry object
+ JSONObject fileEntry = FileUtils.getEntry(file);
+
+ result = new PluginResult(PluginResult.Status.OK, fileEntry);
+ } catch (FileNotFoundException e) {
+ JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection);
+ Log.e(LOG_TAG, error.toString(), e);
+ result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+ } catch (IOException e) {
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection);
+ Log.e(LOG_TAG, error.toString(), e);
+ result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ result = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ } catch (Throwable e) {
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection);
+ Log.e(LOG_TAG, error.toString(), e);
+ result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
+ } finally {
+ safeClose(outputStream);
+ synchronized (activeRequests) {
+ activeRequests.remove(objectId);
+ }
+
+ if (connection != null) {
+ // Revert back to the proper verifier and socket factories
+ if (trustEveryone && useHttps) {
+ HttpsURLConnection https = (HttpsURLConnection) connection;
+ https.setHostnameVerifier(oldHostnameVerifier);
+ https.setSSLSocketFactory(oldSocketFactory);
+ }
+ }
+
+ if (result == null) {
+ result = new PluginResult(PluginResult.Status.ERROR, createFileTransferError(CONNECTION_ERR, source, target, connection));
+ }
+ // Remove incomplete download.
+ if (result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) {
+ file.delete();
+ }
+ context.sendPluginResult(result);
+ }
+ }
+ });
+ }
+
+ /**
+ * Abort an ongoing upload or download.
+ */
+ private void abort(String objectId) {
+ final RequestContext context;
+ synchronized (activeRequests) {
+ context = activeRequests.remove(objectId);
+ }
+ if (context != null) {
+ File file = context.targetFile;
+ if (file != null) {
+ file.delete();
+ }
+ // Trigger the abort callback immediately to minimize latency between it and abort() being called.
+ JSONObject error = createFileTransferError(ABORTED_ERR, context.source, context.target, null, -1);
+ synchronized (context) {
+ context.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, error));
+ context.aborted = true;
+ }
+ // Closing the streams can block, so execute on a background thread.
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ synchronized (context) {
+ safeClose(context.currentInputStream);
+ safeClose(context.currentOutputStream);
+ }
+ }
+ });
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/a80ae041/test/cordova-incl.js
----------------------------------------------------------------------
diff --git a/test/cordova-incl.js b/test/cordova-incl.js
index a82c590..bd612be 100644
--- a/test/cordova-incl.js
+++ b/test/cordova-incl.js
@@ -22,6 +22,7 @@
var PLAT;
(function getPlatform() {
var platforms = {
+ amazon_fireos: /cordova-amazon-fireos/,
android: /Android/,
ios: /(iPad)|(iPhone)|(iPod)/,
blackberry10: /(BB10)/,
@@ -76,7 +77,7 @@ if (!window._doNotWriteCordovaScript) {
}
function backHome() {
- if (window.device && device.platform && device.platform.toLowerCase() == 'android') {
+ if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) {
navigator.app.backHistory();
}
else {
[5/9] git commit: CB-5466: Minor version bump
Posted by st...@apache.org.
CB-5466: Minor version bump
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/a61f0f3d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/a61f0f3d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/a61f0f3d
Branch: refs/heads/master
Commit: a61f0f3d50078590ae4fef099cd9a4d2e4bde751
Parents: 2f1411f
Author: Ian Clelland <ic...@chromium.org>
Authored: Fri Nov 22 10:20:57 2013 -0500
Committer: Ian Clelland <ic...@chromium.org>
Committed: Fri Nov 22 10:31:59 2013 -0500
----------------------------------------------------------------------
plugin.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/a61f0f3d/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index d1de8dd..529617f 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -2,7 +2,7 @@
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="org.apache.cordova.file-transfer"
- version="0.3.5-dev">
+ version="0.4.0-dev">
<name>File Transfer</name>
<description>Cordova File Transfer Plugin</description>
<license>Apache 2.0</license>