You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
11 KiB
JavaScript
294 lines
11 KiB
JavaScript
11 years ago
|
/**
|
||
|
* @license
|
||
|
* Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
|
||
|
*
|
||
|
* @licstart
|
||
|
* The JavaScript code in this page is free software: you can redistribute it
|
||
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||
|
* (GNU AGPL) as published by the Free Software Foundation, either version 3 of
|
||
|
* the License, or (at your option) any later version. The code is distributed
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
|
||
|
*
|
||
|
* As additional permission under GNU AGPL version 3 section 7, you
|
||
|
* may distribute non-source (e.g., minimized or compacted) forms of
|
||
|
* that code without the copy of the GNU GPL normally required by
|
||
|
* section 4, provided you include this license notice and a URL
|
||
|
* through which recipients can access the Corresponding Source.
|
||
|
*
|
||
|
* As a special exception to the AGPL, any HTML file which merely makes function
|
||
|
* calls to this code, and for that purpose includes it by reference shall be
|
||
|
* deemed a separate work for copyright law purposes. In addition, the copyright
|
||
|
* holders of this code give you permission to combine this code with free
|
||
|
* software libraries that are released under the GNU LGPL. You may copy and
|
||
|
* distribute such a system following the terms of the GNU AGPL for this code
|
||
|
* and the LGPL for the libraries. If you modify this code, you may extend this
|
||
|
* exception to your version of the code, but you are not obligated to do so.
|
||
|
* If you do not wish to do so, delete this exception statement from your
|
||
|
* version.
|
||
|
*
|
||
|
* This license applies to this entire compilation.
|
||
|
* @licend
|
||
|
* @source: http://www.webodf.org/
|
||
|
* @source: http://gitorious.org/webodf/webodf/
|
||
|
*/
|
||
|
|
||
|
/*global XMLHttpRequest, runtime, core, ops*/
|
||
|
|
||
|
define("webodf/editor/server/pullbox/Server", [], function () {
|
||
|
"use strict";
|
||
|
|
||
|
runtime.loadClass("core.Base64");
|
||
|
runtime.loadClass("core.ByteArrayWriter");
|
||
|
|
||
|
/**
|
||
|
* @constructor
|
||
|
* @implements ops.Server
|
||
|
* @param {{url:string}} args
|
||
|
*/
|
||
|
return function PullBoxServer(args) {
|
||
|
|
||
|
var self = this,
|
||
|
token,
|
||
|
base64 = new core.Base64();
|
||
|
|
||
|
args = args || {};
|
||
|
args.url = args.url || "/WSER";
|
||
|
args.sessionStateToFileUrl = args.sessionStateToFileUrl || "/SS2F"
|
||
|
|
||
|
this.getGenesisUrl = function (sessionId) {
|
||
|
return "/session/" + sessionId + "/genesis";
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param {!Object} message
|
||
|
* @param {!function(!string)} cb
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
function call(message, cb) {
|
||
|
var xhr = new XMLHttpRequest(),
|
||
|
byteArrayWriter = new core.ByteArrayWriter("utf8"),
|
||
|
messageString = JSON.stringify(message),
|
||
|
data;
|
||
|
|
||
|
function handleResult() {
|
||
|
if (xhr.readyState === 4) {
|
||
|
if ((xhr.status < 200 || xhr.status >= 300) && xhr.status === 0) {
|
||
|
// report error
|
||
|
runtime.log("Status " + String(xhr.status) + ": " +
|
||
|
xhr.responseText || xhr.statusText);
|
||
|
}
|
||
|
cb(xhr.responseText);
|
||
|
}
|
||
|
}
|
||
|
runtime.log("Sending message to server: "+messageString);
|
||
|
// create body data for request from metadata and payload
|
||
|
byteArrayWriter.appendString(messageString);
|
||
|
// byteArrayWriter.appendByteArray(zipData);
|
||
|
data = byteArrayWriter.getByteArray();
|
||
|
|
||
|
// do the request
|
||
|
xhr.open('POST', args.url, true);
|
||
|
xhr.onreadystatechange = handleResult;
|
||
|
// ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
|
||
|
// an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
|
||
|
if (data.buffer && !xhr.sendAsBinary) {
|
||
|
data = data.buffer; // webkit supports sending an ArrayBuffer
|
||
|
} else {
|
||
|
// encode into a string, this works in FireFox >= 3
|
||
|
data = runtime.byteArrayToString(data, "binary");
|
||
|
}
|
||
|
try {
|
||
|
if (xhr.sendAsBinary) {
|
||
|
xhr.sendAsBinary(data);
|
||
|
} else {
|
||
|
xhr.send(data);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
runtime.log("Problem with calling server: " + e + " " + data);
|
||
|
cb(e.message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.call = call;
|
||
|
|
||
|
this.getToken = function () {
|
||
|
return token;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* for pre-authenticated use
|
||
|
*/
|
||
|
this.setToken = function (a_token) {
|
||
|
token = a_token;
|
||
|
};
|
||
|
|
||
|
|
||
|
/*jslint unparam: true*/
|
||
|
/**
|
||
|
* @param {!number} timeout in milliseconds
|
||
|
* @param {!function(!string)} callback
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
this.connect = function (timeout, callback) {
|
||
|
/*
|
||
|
var accumulatedWaitingTime = 0;
|
||
|
|
||
|
// already tried connecting?
|
||
|
if (self.networkStatus() === "ready") {
|
||
|
return;
|
||
|
}
|
||
|
*/
|
||
|
callback("ready");
|
||
|
};
|
||
|
/*jslint unparam: false*/
|
||
|
|
||
|
/**
|
||
|
* @return {!string}
|
||
|
*/
|
||
|
this.networkStatus = function () {
|
||
|
return "ready";
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param {!string} login
|
||
|
* @param {!string} password
|
||
|
* @param {function(!Object)} successCb
|
||
|
* @param {function(!string)} failCb
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
this.login = function (login, password, successCb, failCb) {
|
||
|
call({
|
||
|
command: "login",
|
||
|
args: {
|
||
|
login: base64.toBase64(login),
|
||
|
password: base64.toBase64(password)
|
||
|
}
|
||
|
}, function(responseData) {
|
||
|
var response = /**@type {{token:string}}*/(runtime.fromJson(responseData));
|
||
|
runtime.log("Login reply: " + responseData);
|
||
|
|
||
|
if (response.hasOwnProperty("token")) {
|
||
|
token = response.token;
|
||
|
runtime.log("Caching token: " + self.getToken());
|
||
|
successCb(response);
|
||
|
} else {
|
||
|
failCb(responseData);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param {!string} userId
|
||
|
* @param {!string} sessionId
|
||
|
* @param {!function(!string)} successCb
|
||
|
* @param {function()=} failCb
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
this.joinSession = function (userId, sessionId, successCb, failCb) {
|
||
|
call({
|
||
|
command: "join_session",
|
||
|
args: {
|
||
|
user_id: userId,
|
||
|
es_id: sessionId
|
||
|
}
|
||
|
}, function(responseData) {
|
||
|
var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
|
||
|
runtime.log("join_session reply: " + responseData);
|
||
|
|
||
|
if (response.hasOwnProperty("success") && response.success) {
|
||
|
successCb(response.member_id);
|
||
|
} else {
|
||
|
if (failCb) {
|
||
|
failCb();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param {!string} sessionId
|
||
|
* @param {!string} memberId
|
||
|
* @param {!function()} successCb
|
||
|
* @param {function()=} failCb
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
this.leaveSession = function (sessionId, memberId, successCb, failCb) {
|
||
|
call({
|
||
|
command: "leave_session",
|
||
|
args: {
|
||
|
es_id: sessionId,
|
||
|
member_id: memberId
|
||
|
}
|
||
|
}, function(responseData) {
|
||
|
var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
|
||
|
runtime.log("leave_session reply: " + responseData);
|
||
|
|
||
|
if (response.hasOwnProperty("success") && response.success) {
|
||
|
successCb();
|
||
|
} else {
|
||
|
if (failCb) {
|
||
|
failCb();
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @param {!string} sessionId
|
||
|
* @param {!string} memberId
|
||
|
* @param {!string} seqHead
|
||
|
* @param {function()=} callback
|
||
|
* @return {undefined}
|
||
|
*/
|
||
|
this.writeSessionStateToFile = function(sessionId, memberId, seqHead, fileData, callback) {
|
||
|
// code copied from BrowserRuntime.writeFile and adapted
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
|
||
|
function handleResult() {
|
||
|
if (xhr.readyState === 4) {
|
||
|
if (xhr.status === 0 && !xhr.responseText) {// TODO: check makes sense here as well?
|
||
|
// for local files there is no difference between missing
|
||
|
// and empty files, so empty files are considered as errors
|
||
|
runtime.log("File " + args.sessionStateToFileUrl + " is empty.");
|
||
|
} else if ((xhr.status >= 200 && xhr.status < 300) ||
|
||
|
xhr.status === 0) {
|
||
|
// report success
|
||
|
runtime.log(null);
|
||
|
} else {
|
||
|
// report error
|
||
|
runtime.log("Status " + String(xhr.status) + ": " +
|
||
|
xhr.responseText || xhr.statusText);
|
||
|
}
|
||
|
callback();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// do the request
|
||
|
xhr.open('POST', args.sessionStateToFileUrl, true);
|
||
|
xhr.setRequestHeader("x-webodf-es_id", sessionId);
|
||
|
xhr.setRequestHeader("x-webodf-member_id", memberId);
|
||
|
xhr.setRequestHeader("x-webodf-seq_head", seqHead);
|
||
|
xhr.onreadystatechange = handleResult;
|
||
|
// ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
|
||
|
// an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
|
||
|
if (fileData.buffer && !xhr.sendAsBinary) {
|
||
|
fileData = fileData.buffer; // webkit supports sending an ArrayBuffer
|
||
|
} else {
|
||
|
// encode into a string, this works in FireFox >= 3
|
||
|
fileData = runtime.byteArrayToString(fileData, "binary");
|
||
|
}
|
||
|
try {
|
||
|
if (xhr.sendAsBinary) {
|
||
|
xhr.sendAsBinary(fileData);
|
||
|
} else {
|
||
|
xhr.send(fileData);
|
||
|
}
|
||
|
} catch (e) {
|
||
|
runtime.log("Problem with calling \"writeSessionStateToFile\" on server");
|
||
|
callback(e.message);
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
});
|