Upload document to Vereign
Save document to a input format (either PDF, ODT, DOCX) and send the document to Vereign using WOPI protocol. Change-Id: If9a7d88e91d07c7f1f831c01793f0f73d7a98131 Reviewed-on: https://gerrit.libreoffice.org/63839 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
This commit is contained in:
parent
91218de5b0
commit
5b22fac214
5 changed files with 176 additions and 2 deletions
|
@ -21,12 +21,19 @@
|
|||
#include <Poco/JSON/Parser.h>
|
||||
#include <Poco/Net/WebSocket.h>
|
||||
#include <Poco/StringTokenizer.h>
|
||||
#include <Poco/StreamCopier.h>
|
||||
#include <Poco/URI.h>
|
||||
#include <Poco/BinaryReader.h>
|
||||
#include <Poco/Base64Decoder.h>
|
||||
#include <Poco/Net/HTTPResponse.h>
|
||||
#include <Poco/Net/HTTPSClientSession.h>
|
||||
#include <Poco/Net/SSLManager.h>
|
||||
#include <Poco/Net/KeyConsoleHandler.h>
|
||||
#include <Poco/Net/AcceptCertificateHandler.h>
|
||||
|
||||
#include <common/FileUtil.hpp>
|
||||
#include <common/JsonUtil.hpp>
|
||||
#include <common/Authorization.hpp>
|
||||
#include "KitHelper.hpp"
|
||||
#include <Log.hpp>
|
||||
#include <Png.hpp>
|
||||
|
@ -263,7 +270,8 @@ bool ChildSession::_handleInput(const char *buffer, int length)
|
|||
tokens[0] == "userinactive" ||
|
||||
tokens[0] == "windowcommand" ||
|
||||
tokens[0] == "asksignaturestatus" ||
|
||||
tokens[0] == "signdocument");
|
||||
tokens[0] == "signdocument" ||
|
||||
tokens[0] == "uploadsigneddocument");
|
||||
|
||||
if (tokens[0] == "clientzoom")
|
||||
{
|
||||
|
@ -357,6 +365,10 @@ bool ChildSession::_handleInput(const char *buffer, int length)
|
|||
{
|
||||
askSignatureStatus(buffer, length, tokens);
|
||||
}
|
||||
else if (tokens[0] == "uploadsigneddocument")
|
||||
{
|
||||
return uploadSignedDocument(buffer, length, tokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false && "Unknown command token.");
|
||||
|
@ -366,6 +378,137 @@ bool ChildSession::_handleInput(const char *buffer, int length)
|
|||
return true;
|
||||
}
|
||||
|
||||
// add to common / tools
|
||||
size_t getFileSize(const std::string& filename)
|
||||
{
|
||||
return std::ifstream(filename, std::ifstream::ate | std::ifstream::binary).tellg();
|
||||
}
|
||||
|
||||
std::string getMimeFromFileType(const std::string & fileType)
|
||||
{
|
||||
if (fileType == "pdf")
|
||||
return "application/pdf";
|
||||
else if (fileType == "odt")
|
||||
return "application/vnd.oasis.opendocument.text";
|
||||
else if (fileType == "docx")
|
||||
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool ChildSession::uploadSignedDocument(const char* buffer, int length, const std::vector<std::string>& /*tokens*/)
|
||||
{
|
||||
std::string filename;
|
||||
std::string wopiUrl;
|
||||
std::string token;
|
||||
std::string filetype;
|
||||
|
||||
{ // parse JSON
|
||||
const std::string firstLine = getFirstLine(buffer, length);
|
||||
|
||||
const char* data = buffer + firstLine.size() + 1;
|
||||
const int size = length - firstLine.size() - 1;
|
||||
std::string json(data, size);
|
||||
|
||||
Poco::JSON::Parser parser;
|
||||
Poco::JSON::Object::Ptr root = parser.parse(json).extract<Poco::JSON::Object::Ptr>();
|
||||
|
||||
filename = JsonUtil::getJSONValue<std::string>(root, "filename");
|
||||
wopiUrl = JsonUtil::getJSONValue<std::string>(root, "wopiUrl");
|
||||
token = JsonUtil::getJSONValue<std::string>(root, "token");
|
||||
filetype = JsonUtil::getJSONValue<std::string>(root, "type");
|
||||
}
|
||||
|
||||
if (filetype.empty() || filename.empty() || wopiUrl.empty() || token.empty())
|
||||
{
|
||||
sendTextFrame("error: cmd=uploadsigneddocument kind=syntax");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string mimetype = getMimeFromFileType(filetype);
|
||||
if (mimetype.empty())
|
||||
{
|
||||
sendTextFrame("error: cmd=uploadsigneddocument kind=syntax");
|
||||
return false;
|
||||
}
|
||||
const std::string tmpDir = FileUtil::createRandomDir(JAILED_DOCUMENT_ROOT);
|
||||
const Poco::Path filenameParam(filename);
|
||||
const std::string url = JAILED_DOCUMENT_ROOT + tmpDir + "/" + filenameParam.getFileName();
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
|
||||
|
||||
getLOKitDocument()->saveAs(url.c_str(),
|
||||
filetype.empty() ? nullptr : filetype.c_str(),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
Authorization authorization(Authorization::Type::Token, token);
|
||||
Poco::URI uriObject(wopiUrl + "/" + filename + "/contents");
|
||||
|
||||
authorization.authorizeURI(uriObject);
|
||||
|
||||
try
|
||||
{
|
||||
Poco::Net::initializeSSL();
|
||||
Poco::Net::Context::Params sslClientParams;
|
||||
sslClientParams.verificationMode = Poco::Net::Context::VERIFY_NONE;
|
||||
Poco::SharedPtr<Poco::Net::PrivateKeyPassphraseHandler> consoleClientHandler = new Poco::Net::KeyConsoleHandler(false);
|
||||
Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> invalidClientCertHandler = new Poco::Net::AcceptCertificateHandler(false);
|
||||
Poco::Net::Context::Ptr sslClientContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, sslClientParams);
|
||||
Poco::Net::SSLManager::instance().initializeClient(consoleClientHandler, invalidClientCertHandler, sslClientContext);
|
||||
|
||||
std::unique_ptr<Poco::Net::HTTPClientSession> psession;
|
||||
psession.reset(new Poco::Net::HTTPSClientSession(
|
||||
uriObject.getHost(),
|
||||
uriObject.getPort(),
|
||||
Poco::Net::SSLManager::instance().defaultClientContext()));
|
||||
|
||||
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
|
||||
request.set("User-Agent", WOPI_AGENT_STRING);
|
||||
authorization.authorizeRequest(request);
|
||||
|
||||
request.set("X-WOPI-Override", "PUT");
|
||||
|
||||
const size_t filesize = getFileSize(url);
|
||||
|
||||
request.setContentType(mimetype);
|
||||
request.setContentLength(filesize);
|
||||
|
||||
std::ostream& httpOutputStream = psession->sendRequest(request);
|
||||
|
||||
std::ifstream inputFileStream(url);
|
||||
Poco::StreamCopier::copyStream(inputFileStream, httpOutputStream);
|
||||
|
||||
Poco::Net::HTTPResponse response;
|
||||
std::istream& responseStream = psession->receiveResponse(response);
|
||||
|
||||
std::ostringstream outputStringStream;
|
||||
Poco::StreamCopier::copyStream(responseStream, outputStringStream);
|
||||
std::string responseString = outputStringStream.str();
|
||||
|
||||
if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK &&
|
||||
response.getStatus() != Poco::Net::HTTPResponse::HTTP_CREATED)
|
||||
{
|
||||
LOG_ERR("Upload signed document HTTP Response Error: " << response.getStatus() << ' ' << response.getReason());
|
||||
|
||||
sendTextFrame("error: cmd=uploadsigneddocument kind=httpresponse");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception& pocoException)
|
||||
{
|
||||
LOG_ERR("Upload signed document Exception: " + pocoException.displayText());
|
||||
|
||||
sendTextFrame("error: cmd=uploadsigneddocument kind=failure");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, const std::vector<std::string>& tokens)
|
||||
{
|
||||
int part = -1;
|
||||
|
|
|
@ -263,6 +263,7 @@ private:
|
|||
bool sendWindowCommand(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool signDocumentContent(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool askSignatureStatus(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
bool uploadSignedDocument(const char* buffer, int length, const std::vector<std::string>& tokens);
|
||||
|
||||
void rememberEventsForInactiveUser(const int type, const std::string& payload);
|
||||
|
||||
|
|
|
@ -954,6 +954,7 @@ function initNormalToolbar(toolItems) {
|
|||
{type: 'html', id: 'left'},
|
||||
{type: 'html', id: 'logo', html: '<p><b>Vereign</b></p>'},
|
||||
{type: 'button', id: 'sign', caption: 'Sign', img: '', hint: _('Sign document')},
|
||||
{type: 'button', id: 'upload', caption: 'Upload', img: '', hint: _('Upload document')},
|
||||
{type: 'break' },
|
||||
{type: 'html', id: 'identity-label', html: '<b>Identity:</b>'},
|
||||
{type: 'html', id: 'identity', html: 'N/A'},
|
||||
|
|
|
@ -86,11 +86,13 @@ function adjustUIState() {
|
|||
w2ui['document-signing-bar'].show('passport');
|
||||
w2ui['document-signing-bar'].show('current-passport');
|
||||
w2ui['document-signing-bar'].show('sign');
|
||||
w2ui['document-signing-bar'].show('upload');
|
||||
}
|
||||
else {
|
||||
w2ui['document-signing-bar'].show('passport');
|
||||
w2ui['document-signing-bar'].hide('current-passport');
|
||||
w2ui['document-signing-bar'].hide('sign');
|
||||
w2ui['document-signing-bar'].hide('upload');
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -103,6 +105,7 @@ function adjustUIState() {
|
|||
w2ui['document-signing-bar'].hide('identity-label');
|
||||
w2ui['document-signing-bar'].hide('identity');
|
||||
w2ui['document-signing-bar'].hide('sign');
|
||||
w2ui['document-signing-bar'].hide('upload');
|
||||
w2ui['document-signing-bar'].hide('passport');
|
||||
w2ui['document-signing-bar'].hide('current-passport');
|
||||
}
|
||||
|
@ -244,6 +247,31 @@ L.Map.include({
|
|||
}
|
||||
}
|
||||
},
|
||||
uploadToVereign: function() {
|
||||
if (library == null) {
|
||||
return;
|
||||
}
|
||||
var map = this;
|
||||
var filename = 'fileId'; // need to read the filename
|
||||
|
||||
library.getPassports(filename).then(function(result) {
|
||||
if (isSuccess(result)) {
|
||||
var resultArray = result.data;
|
||||
for (var i = 0; i < resultArray.length; i++) {
|
||||
if (currentPassport.uuid == resultArray[i].PassportUUID) {
|
||||
var jsonRequest = {
|
||||
filename: filename,
|
||||
wopiUrl: vereignURL + '/wopi/files',
|
||||
token: resultArray[i].AccessToken,
|
||||
type: 'pdf'
|
||||
};
|
||||
var blob = new Blob(['uploadsigneddocument\n', JSON.stringify(jsonRequest)]);
|
||||
map._socket.sendMessage(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
signingLogout: function() {
|
||||
if (library) {
|
||||
library.logout().then(function(result) {
|
||||
|
|
|
@ -173,7 +173,8 @@ bool ClientSession::_handleInput(const char *buffer, int length)
|
|||
tokens[0] != "paintwindow" &&
|
||||
tokens[0] != "windowcommand" &&
|
||||
tokens[0] != "signdocument" &&
|
||||
tokens[0] != "asksignaturestatus")
|
||||
tokens[0] != "asksignaturestatus" &&
|
||||
tokens[0] != "uploadsigneddocument")
|
||||
{
|
||||
sendTextFrame("error: cmd=" + tokens[0] + " kind=unknown");
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue