(js) Add support for XSRF token with downloads

Initial support to download a file from an Ajax query. This allows the
XSRF token to be sent and verified by the server.
pull/207/head
Francis Lachapelle 2016-05-03 12:55:58 -04:00
parent 7bf7a34a78
commit 64ce63d812
10 changed files with 81 additions and 18 deletions

View File

@ -369,16 +369,15 @@
SOGoMailFolder *co;
WOResponse *response;
NSArray *uids;
NSDictionary *jsonResponse;
NSString *value;
NSDictionary *data, *jsonResponse;
co = [self clientObject];
value = [[context request] formValueForKey: @"uid"];
data = [[[context request] contentAsString] objectFromJSONString];
uids = [data objectForKey: @"uids"];
response = nil;
if ([value length] > 0)
if ([uids count] > 0)
{
uids = [value componentsSeparatedByString: @","];
response = [co archiveUIDs: uids
inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
inContext: context];
@ -387,7 +386,7 @@
}
else
{
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uid' parameter." inContext: context]
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uids' parameter." inContext: context]
forKey: @"message"];
response = [self responseWithStatus: 500 andJSONRepresentation: jsonResponse];
}

View File

@ -180,7 +180,7 @@
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="mailbox.saveSelectedMessages()">
<md-button ng-click="mailbox.selectedFolder.saveSelectedMessages()">
<var:string label:value="Save As..."/>
</md-button>
</md-menu-item>

View File

@ -8,7 +8,7 @@
xmlns:label="OGo:label"
className="UIxPageFrame"
title="title"
const:jsFiles="Common.js, Preferences.services.js, Contacts.services.js, Scheduler.services.js, Mailer.js, Mailer.services.js, vendor/ckeditor/ckeditor.js, vendor/ckeditor/ck.js, vendor/angular-file-upload.min.js">
const:jsFiles="Common.js, Preferences.services.js, Contacts.services.js, Scheduler.services.js, Mailer.js, Mailer.services.js, vendor/ckeditor/ckeditor.js, vendor/ckeditor/ck.js, vendor/angular-file-upload.min.js, vendor/FileSaver.min.js">
<script type="text/javascript">
var mailAccounts = <var:string value="mailAccounts" const:escapeHTML="NO" />;
var userNames = <var:string value="userNames" const:escapeHTML="NO" />;

View File

@ -17,7 +17,8 @@ module.exports = function(grunt) {
};
var custom_vendor_files = {
'js/vendor/ng-sortable.min.js': ['bower_components/Sortable/Sortable.js', 'bower_components/Sortable/ng-sortable.js'],
'js/vendor/angular-file-upload.min.js': ['bower_components/angular-file-upload/dist/angular-file-upload.js', 'js/Common/angular-file-upload.trump.js']
'js/vendor/angular-file-upload.min.js': ['bower_components/angular-file-upload/dist/angular-file-upload.js', 'js/Common/angular-file-upload.trump.js'],
'js/vendor/FileSaver.min.js': ['bower_components/file-saver.js/FileSaver.js']
};
require('time-grunt')(grunt);

View File

@ -11,6 +11,7 @@
"angular-ui-router": "latest",
"angular-file-upload": "latest",
"angular-material": ">v1.1.0-rc4-master",
"file-saver.js": "latest",
"lodash": "latest",
"Sortable": "latest",
"breakpoint-sass": ">=2.4.2"

View File

@ -154,12 +154,63 @@
* @return a promise
*/
Resource.prototype.save = function(id, newValue, options) {
var deferred = this._q.defer(),
action = (options && options.action)? options.action : 'save';
var action = (options && options.action)? options.action : 'save';
return this.post(id, action, newValue);
};
/**
* @function download
* @memberof Resource.prototype
* @desc Download a file from the server. Requires FileSaver.js.
* @see {@link http://blog.davidjs.com/2015/07/download-files-via-post-request-in-angularjs/|Download files via POST request in AngularJs}
* @see {@link https://github.com/eligrey/FileSaver.js|FileSaver.js}
* @return a promise
*/
Resource.prototype.download = function(id, action, data, options) {
var deferred = this._q.defer(),
type = (options && options.type)? options.type : 'application/zip',
path = [this._path];
if (id) path.push(id);
if (action) path.push(action);
path = _.compact(_.flatten(path)).join('/');
function getFileNameFromHeader(header) {
var result;
if (!header) return null;
result = header.split(";")[1].trim().split("=")[1];
return result.replace(/"/g, '');
}
return this._http({
method: 'POST',
url: path,
data: data,
headers: {
accept: type
},
responseType: 'arraybuffer',
cache: false,
transformResponse: function (data, headers) {
var fileName, result, blob = null;
if (data) {
blob = new Blob([data], { type: type });
}
fileName = getFileNameFromHeader(headers('content-disposition'));
if (!saveAs) {
throw new Error('To use Resource.download, FileSaver.js must be loaded.');
}
else {
saveAs(blob, fileName);
}
}
});
};
/**
* @function remove
* @memberof Resource.prototype

View File

@ -530,6 +530,21 @@
return Mailbox.$$resource.post(this.id, 'addOrRemoveLabel', data);
};
/**
* @function saveSelectedMessages
* @memberof Mailbox.prototype
* @desc Download the selected messages
* @returns a promise of the HTTP operation
*/
Mailbox.prototype.saveSelectedMessages = function() {
var selectedMessages, selectedUIDs;
selectedMessages = _.filter(this.$messages, function(message) { return message.selected; });
selectedUIDs = _.map(selectedMessages, 'uid');
return Mailbox.$$resource.download(this.id, 'saveMessages', {uids: selectedUIDs});
};
/**
* @function $delete
* @memberof Mailbox.prototype

View File

@ -26,7 +26,6 @@
vm.markOrUnMarkMessagesAsJunk = markOrUnMarkMessagesAsJunk;
vm.copySelectedMessages = copySelectedMessages;
vm.moveSelectedMessages = moveSelectedMessages;
vm.saveSelectedMessages = saveSelectedMessages;
vm.markSelectedMessagesAsFlagged = markSelectedMessagesAsFlagged;
vm.markSelectedMessagesAsUnread = markSelectedMessagesAsUnread;
vm.selectAll = selectAll;
@ -153,12 +152,6 @@
});
}
function saveSelectedMessages() {
var selectedMessages = _.filter(vm.selectedFolder.$messages, function(message) { return message.selected; });
var selectedUIDs = _.map(selectedMessages, 'uid');
window.location.href = ApplicationBaseURL + '/' + vm.selectedFolder.id + '/saveMessages?uid=' + selectedUIDs.join(",");
}
function selectAll() {
var i = 0, length = vm.selectedFolder.$messages.length;
for (; i < length; i++)

View File

@ -0,0 +1,2 @@
var saveAs=saveAs||function(a){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var b=a.document,c=function(){return a.URL||a.webkitURL||a},d=b.createElementNS("http://www.w3.org/1999/xhtml","a"),e="download"in d,f=function(c){var d=b.createEvent("MouseEvents");d.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null),c.dispatchEvent(d)},g=a.webkitRequestFileSystem,h=a.requestFileSystem||g||a.mozRequestFileSystem,i=function(b){(a.setImmediate||a.setTimeout)(function(){throw b},0)},j="application/octet-stream",k=0,l=500,m=function(b){var d=function(){"string"==typeof b?c().revokeObjectURL(b):b.remove()};a.chrome?d():setTimeout(d,l)},n=function(a,b,c){b=[].concat(b);for(var d=b.length;d--;){var e=a["on"+b[d]];if("function"==typeof e)try{e.call(a,c||a)}catch(f){i(f)}}},o=function(a){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\ufeff",a],{type:a.type}):a},p=function(b,i){b=o(b);var l,p,q,r=this,s=b.type,t=!1,u=function(){n(r,"writestart progress write writeend".split(" "))},v=function(){if((t||!l)&&(l=c().createObjectURL(b)),p)p.location.href=l;else{var d=a.open(l,"_blank");void 0==d&&"undefined"!=typeof safari&&(a.location.href=l)}r.readyState=r.DONE,u(),m(l)},w=function(a){return function(){return r.readyState!==r.DONE?a.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};return r.readyState=r.INIT,i||(i="download"),e?(l=c().createObjectURL(b),d.href=l,d.download=i,f(d),r.readyState=r.DONE,u(),void m(l)):(a.chrome&&s&&s!==j&&(q=b.slice||b.webkitSlice,b=q.call(b,0,b.size,j),t=!0),g&&"download"!==i&&(i+=".download"),(s===j||g)&&(p=a),h?(k+=b.size,void h(a.TEMPORARY,k,w(function(a){a.root.getDirectory("saved",x,w(function(a){var c=function(){a.getFile(i,x,w(function(a){a.createWriter(w(function(c){c.onwriteend=function(b){p.location.href=a.toURL(),r.readyState=r.DONE,n(r,"writeend",b),m(a)},c.onerror=function(){var a=c.error;a.code!==a.ABORT_ERR&&v()},"writestart progress write abort".split(" ").forEach(function(a){c["on"+a]=r["on"+a]}),c.write(b),r.abort=function(){c.abort(),r.readyState=r.DONE},r.readyState=r.WRITING}),v)}),v)};a.getFile(i,{create:!1},w(function(a){a.remove(),c()}),w(function(a){a.code===a.NOT_FOUND_ERR?c():v()}))}),v)}),v)):void v())},q=p.prototype,r=function(a,b){return new p(a,b)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(a,b){return navigator.msSaveOrOpenBlob(o(a),b)}:(q.abort=function(){var a=this;a.readyState=a.DONE,n(a,"abort")},q.readyState=q.INIT=0,q.WRITING=1,q.DONE=2,q.error=q.onwritestart=q.onprogress=q.onwrite=q.onabort=q.onerror=q.onwriteend=null,r)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs});
//# sourceMappingURL=FileSaver.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../bower_components/file-saver.js/FileSaver.js"],"names":["saveAs","view","navigator","test","userAgent","doc","document","get_URL","URL","webkitURL","save_link","createElementNS","can_use_save_link","click","node","event","createEvent","initMouseEvent","dispatchEvent","webkit_req_fs","webkitRequestFileSystem","req_fs","requestFileSystem","mozRequestFileSystem","throw_outside","ex","setImmediate","setTimeout","force_saveable_type","fs_min_size","arbitrary_revoke_timeout","revoke","file","revoker","revokeObjectURL","remove","chrome","dispatch","filesaver","event_types","concat","i","length","listener","call","auto_bom","blob","type","Blob","FileSaver","name","object_url","target_view","slice","this","blob_changed","dispatch_all","split","fs_error","createObjectURL","location","href","new_tab","open","undefined","safari","readyState","DONE","abortable","func","apply","arguments","create_if_not_found","create","exclusive","INIT","download","webkitSlice","size","TEMPORARY","fs","root","getDirectory","dir","save","getFile","createWriter","writer","onwriteend","toURL","onerror","error","code","ABORT_ERR","forEach","write","abort","WRITING","NOT_FOUND_ERR","FS_proto","prototype","msSaveOrOpenBlob","onwritestart","onprogress","onwrite","onabort","self","window","content","module","exports","define","amd"],"mappings":"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","file":"FileSaver.min.js"}