aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js')
-rw-r--r--trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js319
1 files changed, 319 insertions, 0 deletions
diff --git a/trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js b/trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js
new file mode 100644
index 0000000..b7e5f4d
--- /dev/null
+++ b/trunk/etherpad/src/etherpad/control/pad/pad_importexport_control.js
@@ -0,0 +1,319 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * 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.
+ */
+
+import("jsutils.arrayToSet");
+import("stringutils.{toHTML,md5}");
+import("stringutils");
+import("sync");
+import("varz");
+
+import("etherpad.control.pad.pad_view_control.getRevisionInfo");
+import("etherpad.helpers");
+import("etherpad.importexport.importexport");
+import("etherpad.log");
+import("etherpad.pad.model");
+import("etherpad.pad.padutils");
+import("etherpad.pad.importhtml");
+import("etherpad.pad.exporthtml");
+import("etherpad.sessions");
+import("etherpad.sessions.getSession");
+import("etherpad.utils.{render404,renderFramedError}");
+import("etherpad.collab.server_utils");
+
+function _log(obj) {
+ log.custom("import-export", obj);
+}
+
+//---------------------------------------
+// utilities
+//---------------------------------------
+
+function _getPadTextBytes(padId, revNum) {
+ if (revNum === undefined) {
+ return null;
+ }
+ return padutils.accessPadLocal(padId, function(pad) {
+ if (pad.exists()) {
+ var txt = exporthtml.getPadPlainText(pad, revNum);
+ return (new java.lang.String(txt)).getBytes("UTF-8");
+ } else {
+ return null;
+ }
+ }, 'r');
+}
+
+function _getPadHtmlBytes(padId, revNum, noDocType) {
+ if (revNum === undefined) {
+ return null;
+ }
+ var html = padutils.accessPadLocal(padId, function(pad) {
+ if (pad.exists()) {
+ return exporthtml.getPadHTMLDocument(pad, revNum, noDocType);
+ }
+ });
+ if (html) {
+ return (new java.lang.String(html)).getBytes("UTF-8");
+ } else {
+ return null;
+ }
+}
+
+function _getFileExtension(fileName, def) {
+ if (fileName.lastIndexOf('.') > 0) {
+ return fileName.substr(fileName.lastIndexOf('.')+1);
+ } else {
+ return def;
+ }
+}
+
+function _guessFileType(contentType, fileName) {
+ function _f(str) { return function() { return str; }}
+ var unchangedExtensions =
+ arrayToSet(['txt', 'htm', 'html', 'doc', 'docx', 'rtf', 'pdf', 'odt']);
+ var textExtensions =
+ arrayToSet(['js', 'scala', 'java', 'c', 'cpp', 'log', 'h', 'htm', 'html', 'css', 'php', 'xhtml',
+ 'dhtml', 'jsp', 'asp', 'sh', 'bat', 'pl', 'py']);
+ var contentTypes = {
+ 'text/plain': 'txt',
+ 'text/html': 'html',
+ 'application/msword': 'doc',
+ 'application/vnd.oasis.opendocument.text': 'odt',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
+ 'text/rtf': 'rtf',
+ 'application/pdf': 'pdf'
+ }
+
+ var ext = _getFileExtension(fileName);
+ if (ext) {
+ if (unchangedExtensions[ext]) {
+ return ext;
+ } else if (textExtensions[ext]) {
+ return 'txt';
+ }
+ }
+ if (contentType in contentTypes) {
+ return contentTypes[contentType]
+ }
+ // unknown type, nothing to return.
+ _log({type: "warning", error: "unknown-type", contentType: contentType, fileName: fileName});
+}
+
+function _noteExportFailure() {
+ varz.incrementInt("export-failed");
+}
+
+function _noteImportFailure() {
+ varz.incrementInt("import-failed");
+}
+
+//---------------------------------------
+// export
+//---------------------------------------
+
+// handles /ep/pad/export/*
+function renderExport() {
+ var parts = request.path.split('/');
+ var padId = server_utils.parseUrlId(parts[4]).localPadId;
+ var revisionId = parts[5];
+ var rev = null;
+ var format = request.params.format || 'txt';
+
+ if (! request.cache.skipAccess) {
+ _log({type: "request", direction: "export", format: format});
+ rev = getRevisionInfo(padId, revisionId);
+ if (! rev) {
+ render404();
+ }
+ request.cache.skipAccess = true;
+ }
+
+ var result = _exportToFormat(padId, revisionId, (rev || {}).revNum, format);
+ if (result === true) {
+ response.stop();
+ } else {
+ renderFramedError(result);
+ }
+ return true;
+}
+
+function _exportToFormat(padId, revisionId, revNum, format) {
+ var bytes = _doExportConversion(format,
+ function() { return _getPadTextBytes(padId, revNum); },
+ function(noDocType) { return _getPadHtmlBytes(padId, revNum, noDocType); });
+ if (! bytes) {
+ return "Unable to convert file for export... try a different format?"
+ } else if (typeof(bytes) == 'string') {
+ return bytes
+ } else {
+ response.setContentType(importexport.formats[format]);
+ response.setHeader("Content-Disposition", "attachment; filename=\""+padId+"-"+revisionId+"."+format+"\"");
+ response.writeBytes(bytes);
+ return true;
+ }
+}
+
+
+function _doExportConversion(format, getTextBytes, getHtmlBytes) {
+ if (! (format in importexport.formats)) {
+ return false;
+ }
+ var bytes;
+ var srcFormat;
+
+ if (format == 'txt') {
+ bytes = getTextBytes();
+ srcFormat = 'txt';
+ } else {
+ bytes = getHtmlBytes(format == 'doc' || format == 'odt');
+ srcFormat = 'html';
+ }
+ if (bytes == null) {
+ bytes = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 0);
+ }
+
+ try {
+ var ret = importexport.convertFile(srcFormat, format, bytes);
+ if (typeof(ret) == 'string') {
+ _log({type: "error", error: "export-failed", format: format, message: ret});
+ _noteExportFailure();
+ return ret;
+ }
+ bytes = ret;
+ } catch (e) {
+ if (e.javaException instanceof org.mortbay.jetty.RetryRequest) {
+ throw e.javaException
+ }
+ if (e.javaException || e.rhinoException) {
+ net.appjet.oui.exceptionlog.apply(e.javaException || e.rhinoException);
+ }
+ bytes = null;
+ }
+ if (bytes == null || bytes.length == 0) {
+ _log({type: "error", error: "export-failed", format: format, message: ret});
+ _noteExportFailure();
+ return false;
+ }
+ return bytes;
+}
+
+//---------------------------------------
+// import
+//---------------------------------------
+
+function _getImportInfo(key) {
+ var session = getSession();
+ sync.callsyncIfTrue(session, function() { return ! ('importexport' in session) },
+ function() {
+ session.importexport = {};
+ });
+ var tokens = session.importexport;
+ sync.callsyncIfTrue(tokens, function() { return ! (key in tokens) },
+ function() {
+ tokens[key] = {};
+ });
+ return tokens[key];
+}
+
+function render_import() {
+ function _r(code) {
+ response.setContentType("text/html");
+ response.write("<html><body><script>try{parent.document.domain}catch(e){document.domain=document.domain}\n"+code+"</script></body></html>");
+ response.stop();
+ }
+
+ if (! request.isPost) {
+ response.stop();
+ }
+
+ var padId = decodeURIComponent(request.params.padId);
+ if (! padId) {
+ response.stop();
+ }
+
+ var file = request.files.file;
+ if (! file) {
+ _r('parent.pad.handleImportExportFrameCall("importFailed", "Please select a file to import.")');
+ }
+
+ var bytes = file.bytes;
+ var type = _guessFileType(file.contentType, file.filesystemName);
+
+ _log({type: "request", direction: "import", format: type});
+
+ if (! type) {
+ type = _getFileExtension(file.filesystemName, "no file extension found");
+ _r('parent.pad.handleImportExportFrameCall("importFailed", "'+importexport.errorUnsupported(type)+'")');
+ }
+
+ var token = md5(bytes);
+ var state = _getImportInfo(token);
+ state.bytes = bytes;
+ state.type = type;
+
+ _r("parent.pad.handleImportExportFrameCall('importSuccessful', '"+token+"')");
+}
+
+
+function render_import2() {
+ var token = request.params.token;
+
+ function _r(txt) {
+ response.write(txt);
+ response.stop();
+ }
+
+ if (! token) { _r("fail"); }
+
+ var state = _getImportInfo(token);
+ if (! state.type || ! state.bytes) { _r("fail"); }
+
+ var newBytes;
+ try {
+ newBytes = importexport.convertFile(state.type, "html", state.bytes);
+ } catch (e) {
+ if (e.javaException instanceof org.mortbay.jetty.RetryRequest) {
+ throw e.javaException;
+ }
+ net.appjet.oui.exceptionlog.apply(e);
+ throw e;
+ }
+
+ if (typeof(newBytes) == 'string') {
+ _log({type: "error", error: "import-failed", format: state.type, message: newBytes});
+ _noteImportFailure();
+ _r("msg:"+newBytes);
+ }
+
+ if (! newBytes || newBytes.length == 0) {
+ _r("fail");
+ }
+
+ var newHTML;
+ try {
+ newHTML = String(new java.lang.String(newBytes, "UTF-8"));
+ } catch (e) {
+ _r("fail");
+ }
+
+ if (! request.params.padId) { _r("fail"); }
+ padutils.accessPadLocal(request.params.padId, function(pad) {
+ if (! pad.exists()) {
+ _r("fail");
+ }
+ importhtml.setPadHTML(pad, newHTML);
+ });
+ _r("ok");
+}