fix: Libreoffice v0.1.6-a

This commit is contained in:
Dany LE 2025-05-28 22:44:47 +02:00
parent 4a62c4d1cf
commit 5594516697
21 changed files with 164 additions and 56 deletions

View File

@ -9,6 +9,9 @@ It support a wide range of documents.
![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true) ![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true)
## Change log ## Change log
- v 0.1.6-a:
* fix document exporting does not work
* fix missing toolbar icons
- v 0.1.5-a: - v 0.1.5-a:
* allow user to configure document server URI * allow user to configure document server URI
- v 0.1.4-a: - v 0.1.4-a:

View File

@ -13,9 +13,20 @@ local result = function(data)
end end
local error = function(msg) local error = function(msg)
LOG_ERROR("Error: "..msg)
return {error = msg, result = false} return {error = msg, result = false}
end end
local decode_path = function(str)
local encoded = str:gsub("%.(.*)$", ""):gsub('_', '/'):gsub('-', '+')
if #encoded % 4 == 2 then
encoded = encoded.."=="
elseif #encoded %4 == 3 then
encoded = encoded.."="
end
return tostring(enc.b64decode(encoded))
end
local fetch = function(url) local fetch = function(url)
local https = require('ssl.https') local https = require('ssl.https')
local body, code, headers = https.request(url) local body, code, headers = https.request(url)
@ -63,15 +74,19 @@ end
handle.file = function(data) handle.file = function(data)
local rq = REQUEST.r local rq = REQUEST.r
LOG_INFO("Request Data:"..JSON.encode(data))
if not rq then if not rq then
return error("Unknown request") return error("Unknown request")
end end
local ret, stat = vfs.fileinfo(data.file) local ret, stat = vfs.fileinfo(data.file)
if not ret then if not ret then
return error("Unable to query file info") return error("Unable to query file info")
end end
local path = vfs.ospath(data.file) local path = vfs.ospath(data.file)
LOG_INFO("Check for request GET/POST/or data")
if rq:match("/wopi/files/[^/]*/contents$") then if rq:match("/wopi/files/[^/]*/contents$") then
LOG_INFO("/wopi/files/[^/]*/contents$")
if REQUEST.method == "GET" then if REQUEST.method == "GET" then
std.sendFile(path) std.sendFile(path)
return nil return nil
@ -84,14 +99,44 @@ handle.file = function(data)
return error("Unknown request method") return error("Unknown request method")
end end
elseif rq:match("/wopi/files/[^/]*$") then elseif rq:match("/wopi/files/[^/]*$") then
return { LOG_INFO("Matching /wopi/files/[^/]*$")
BaseFileName = stat.name, if REQUEST.method == "GET" then
Size = math.floor(stat.size), return {
UserCanWrite = vfs.checkperm(data.file,"write"), BaseFileName = stat.name,
mime = stat.mime, Size = math.floor(stat.size),
PostMessageOrigin = "*", UserCanWrite = vfs.checkperm(data.file,"write"),
UserCanNotWriteRelative = false mime = stat.mime,
} PostMessageOrigin = "*",
UserCanNotWriteRelative = false
}
elseif REQUEST.method == "POST" then
LOG_INFO("Checking for header X_WOPI_SUGGESTEDTARGET")
local out_file = HEADER['X_WOPI_SUGGESTEDTARGET']
if not out_file then
return error("Unknown request")
end
LOG_INFO("Encoded path:"..out_file)
local dpath = decode_path(out_file)
LOG_INFO("Decoded path:"..dpath)
out_file = vfs.ospath(dpath)
LOG_INFO("Save file to:"..out_file)
local barr = REQUEST["application/octet-stream"]
barr:fileout(out_file)
local ret, stat = vfs.fileinfo(out_file)
if not ret then
return error("Unable to save file")
end
return {
BaseFileName = stat.name,
Size = math.floor(stat.size),
UserCanWrite = vfs.checkperm(data.file,"write"),
mime = stat.mime,
PostMessageOrigin = "*",
UserCanNotWriteRelative = false
}
else
return error("Unknown request method")
end
else else
return error("Unknown request") return error("Unknown request")
end end

View File

@ -52,7 +52,9 @@
"api", "api",
"main.css", "main.css",
"templates", "templates",
"icon.png" "icons/icon.png",
"icons/new.png",
"icons/open.png"
], ],
"dest":"build/debug" "dest":"build/debug"
} }

View File

@ -9,6 +9,9 @@ It support a wide range of documents.
![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true) ![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true)
## Change log ## Change log
- v 0.1.6-a:
* fix document exporting does not work
* fix missing toolbar icons
- v 0.1.5-a: - v 0.1.5-a:
* allow user to configure document server URI * allow user to configure document server URI
- v 0.1.4-a: - v 0.1.4-a:

View File

@ -13,9 +13,20 @@ local result = function(data)
end end
local error = function(msg) local error = function(msg)
LOG_ERROR("Error: "..msg)
return {error = msg, result = false} return {error = msg, result = false}
end end
local decode_path = function(str)
local encoded = str:gsub("%.(.*)$", ""):gsub('_', '/'):gsub('-', '+')
if #encoded % 4 == 2 then
encoded = encoded.."=="
elseif #encoded %4 == 3 then
encoded = encoded.."="
end
return tostring(enc.b64decode(encoded))
end
local fetch = function(url) local fetch = function(url)
local https = require('ssl.https') local https = require('ssl.https')
local body, code, headers = https.request(url) local body, code, headers = https.request(url)
@ -63,15 +74,19 @@ end
handle.file = function(data) handle.file = function(data)
local rq = REQUEST.r local rq = REQUEST.r
LOG_INFO("Request Data:"..JSON.encode(data))
if not rq then if not rq then
return error("Unknown request") return error("Unknown request")
end end
local ret, stat = vfs.fileinfo(data.file) local ret, stat = vfs.fileinfo(data.file)
if not ret then if not ret then
return error("Unable to query file info") return error("Unable to query file info")
end end
local path = vfs.ospath(data.file) local path = vfs.ospath(data.file)
LOG_INFO("Check for request GET/POST/or data")
if rq:match("/wopi/files/[^/]*/contents$") then if rq:match("/wopi/files/[^/]*/contents$") then
LOG_INFO("/wopi/files/[^/]*/contents$")
if REQUEST.method == "GET" then if REQUEST.method == "GET" then
std.sendFile(path) std.sendFile(path)
return nil return nil
@ -84,14 +99,44 @@ handle.file = function(data)
return error("Unknown request method") return error("Unknown request method")
end end
elseif rq:match("/wopi/files/[^/]*$") then elseif rq:match("/wopi/files/[^/]*$") then
return { LOG_INFO("Matching /wopi/files/[^/]*$")
BaseFileName = stat.name, if REQUEST.method == "GET" then
Size = math.floor(stat.size), return {
UserCanWrite = vfs.checkperm(data.file,"write"), BaseFileName = stat.name,
mime = stat.mime, Size = math.floor(stat.size),
PostMessageOrigin = "*", UserCanWrite = vfs.checkperm(data.file,"write"),
UserCanNotWriteRelative = false mime = stat.mime,
} PostMessageOrigin = "*",
UserCanNotWriteRelative = false
}
elseif REQUEST.method == "POST" then
LOG_INFO("Checking for header X_WOPI_SUGGESTEDTARGET")
local out_file = HEADER['X_WOPI_SUGGESTEDTARGET']
if not out_file then
return error("Unknown request")
end
LOG_INFO("Encoded path:"..out_file)
local dpath = decode_path(out_file)
LOG_INFO("Decoded path:"..dpath)
out_file = vfs.ospath(dpath)
LOG_INFO("Save file to:"..out_file)
local barr = REQUEST["application/octet-stream"]
barr:fileout(out_file)
local ret, stat = vfs.fileinfo(out_file)
if not ret then
return error("Unable to save file")
end
return {
BaseFileName = stat.name,
Size = math.floor(stat.size),
UserCanWrite = vfs.checkperm(data.file,"write"),
mime = stat.mime,
PostMessageOrigin = "*",
UserCanNotWriteRelative = false
}
else
return error("Unknown request method")
end
else else
return error("Unknown request") return error("Unknown request")
end end

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -7,7 +7,7 @@
"author": "Dany LE", "author": "Dany LE",
"email": "contact@iohub.dev" "email": "contact@iohub.dev"
}, },
"version":"0.1.5-a", "version":"0.1.6-b",
"category":"Office", "category":"Office",
"icon":"icon.png", "icon":"icon.png",
"mimes":[ "mimes":[

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
LibreOffice/icons/new.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
LibreOffice/icons/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -2,8 +2,8 @@ namespace OS {
export namespace application { export namespace application {
const BUTTON_ICONS = { const BUTTON_ICONS = {
opendoc: "data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAD8UlEQVR42q1Va2gcVRQ+587s7mRItNskfaY1trRi2sZHNYoQHzGmQkAMlNZK1R+l0R+K/REhRAmzIEElaqX2R/tDhZamov4QbV0a6V9Nm9DiI8QEEtpI8zDbPPfh7sw93juzOzv7Ugge2L3nztz7fed859w7CHmGiKocYHVGwswcvLwFWnNzc3tLS8sjaTIvcX4kBZvD4fBAf3//aeEmShGUd3Z2nu7q6noBHZPABOjA2/9ijs4+wiwrydehUKivp6fnqPCjOQSHPhrTmKI2XP/uA33/k9s6Ot58rSkNnvPzZlKQkTDDMM4XJXjp08m3aiqV9xUex3sqZqCtqZ6QMSeDdKQeEoISGQiCvo9PfnY0tjBVQNC9d7vf0Fkcq2AK9jXeR8wrEQB6Ii8gkJWV/skz4ZlLI8posKbOQmQfnnl9y/f2gsMnbnbvuctnaCwOm9QZaH3ifmAlpCklj7RvLw/Bn8lqSPAy+PVGKnT2ja0hN4MdmxTDDzGs1Wbh+aYHXVm8kebNM5m4En3TfxXGY1WUBB3HblmGyCBLsLUaDZViuLN8DvY/s9cL+p8SZQi+DF+BkaW1ZKKON/+iLIGUaEMQDMZjsHtNBA7ue6hAnlISCfldv++HK/DL7SBwpsP0PGQlOnh8onttBRpgruDD6xbgcGtDTgb5EkmXc27XVozus7MXr8Lg7BoCtRznlyF0/litgfUdAxcCqnovAK/l3IRKnWBz9Z155ZMZQEHUcnRcZz41twyROAJj8rZhN5KmOYxtvcMLLz5egxanCimrIiT2qUpBAT1sztzGppw1psXBIlkj0aQIsYHRSAqffnd4fOeWDRoRXy8iYgGBXab5PKDu1SAxwQXOji5BPGlCirNMB94em5xdxGffGx3as23zRotbLoGu+XMzQEgDOagZAqE/SplknUzLwtjfFqDiJ9kTDNn8bxO3JvC53vEfG+o21okF68VWTBN4znnaIUpzkJ2JBBZ1BlVVIJlMwUrCBKb43E2MscXBkekhPHBi8qvHdlc3Eqd1Ygtqoj56ma94Dci5FmT3ZEZRO4jGUwTMZzebXCIlFXkt/Tw8dwlfPjV9qrE+2MYYVckMHAK/q3uGwBN9uj3JliUaN4UsPoK8QyeT+un3hXPY/nmk59FdFa8GfBSUb/2MQ1lALXrXULYOIMDB0bz4BzCaoMTgSPQ4Hju31LHrbu0dXaM7ZDmJmxmof29T+wCq6QNCdmtmw0BcXOHJPyaTb2PvxciRYGX5J5wsvQRocYLSa5yTbiGPLifasfXAkada2g59kTKpuC6rNJ+C1uULX78iPlxKgHPrAfGssqiYqzOZRURRlGv/F2BJ+wdsRP1yLA0KOQAAAABJRU5ErkJggg==", opendoc: "pkg://LibreOffice/open.png".asFileHandle().getlink(),
newdoc: "data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAABmklEQVRIie2Vv0tbURTHP+fmJTGpIYM/KEoUHItOEtIu6uTk2r9BcNMWuro62X9D6OTWIhp00baLCI2giKKYVoMtJtTE93JPhyLSpyavLxE69Due+73nwzn3nnvhkSX+wNut2pugm9XapdkXicO/A3ysaZDk3UnD9yt77KETs9mOg4d8Jkiy+9TTCc8HIpmoSH7xU3Wo7QCA3k5DLtMY0hIgCKRlwB8QI6v+NSds0sKZpXBm/eFBf6AtFTTSf0BThT5kvxRw620G1FUREQxwUraUa3c9LbXoa0XZLbkUSpYBd4Pp+Bz6eTQJoPo7d0sVVD14FZ8mbc5JU8IRF6/CnpsfSXlr5iVsvw9VQa0Ox5eWRP0b/ZF9uqSII+7Nch+QwthJVSTUc31aUXqvN5npeE2Uexp/q5VQFfQkhCN9hquxZtb1f3PQzq+UQflCVK6bWcdCAboSQtHJMf/zHVV98pBt0Rnfmbx7TYWFZoC4A5m0oVh+mr2gP5viIpbUH7GIeAKcAilUPogQ6H9vqJuB8taGp9z88LJ/0H4BR3aNW1eB/4cAAAAASUVORK5CYII=" newdoc: "pkg://LibreOffice/new.png".asFileHandle().getlink()
} }
const DEFAULT_LOO_URL = "https://loo.iohub.dev/hosting/discovery"; const DEFAULT_LOO_URL = "https://loo.iohub.dev/hosting/discovery";
/** /**
@ -163,6 +163,7 @@ namespace OS {
return; return;
let orgevt = e.originalEvent; let orgevt = e.originalEvent;
let data = JSON.parse(orgevt.data); let data = JSON.parse(orgevt.data);
console.log("receive data", data);
switch(data.MessageId) switch(data.MessageId)
{ {
case 'Action_Load_Resp': case 'Action_Load_Resp':
@ -220,7 +221,7 @@ namespace OS {
} }
break; break;
case "UI_SaveAs": case "UI_SaveAs":
this.check_dirty().then((_)=>this.save_as()); this.check_dirty().then((_)=>this.save_as(data.Values.format));
break; break;
default: default:
console.log(data); console.log(data);
@ -228,28 +229,45 @@ namespace OS {
//console.log(this.eid, e); //console.log(this.eid, e);
} }
private save_as() private save_as(format:string = undefined)
{ {
this.openDialog("FileDialog", { if(!format) {
format = this.curr_file.ext;
}
const out_file = `${this.curr_file.parent().path}/${this.curr_file.basename.replace(/\..*$/, '.'+format)}`;
console.log("export file data as ", out_file);
this.openDialog("FileDialog",
{
title: __("Save file as"), title: __("Save file as"),
type: "dir", type: "dir",
file: this.curr_file.asFileHandle() file: out_file.asFileHandle()
}) })
.then(async (d) => { .then(async (d) =>
{
const file = `${d.file.path}/${d.name}`.asFileHandle(); const file = `${d.file.path}/${d.name}`.asFileHandle();
try try
{ {
if(this.curr_file.ext == file.ext)
const r = await this.exec({
action: 'duplicate',
args:{src: this.curr_file.path, dest: file.path}
});
if(r.error)
{ {
throw r.error; const r = await this.exec(
{
action: 'duplicate',
args:{src: this.curr_file.path, dest: file.path}
});
if(r.error)
{
throw r.error;
}
this.curr_file = file;
this.open();
}
else
{
this.post_message("Action_SaveAs", {
Filename: `${this.enb64u(file.path)}.${format}`,
Notify: true
});
} }
this.curr_file = file;
this.open();
} }
catch(e) catch(e)
{ {
@ -453,13 +471,17 @@ namespace OS {
args: {file: this.curr_file.path} args: {file: this.curr_file.path}
} }
} }
// encode data to URL safe base64 encoding // encode data to URL safe base64 encoding
let encoded = let encoded = this.enb64u(JSON.stringify(cmd));
btoa(JSON.stringify(cmd)) return `${this._api.REST}/system/apigateway/${encoded}/wopi/files/${this.curr_file.path.hash()}&${this.access_token}`;
}
private enb64u(input: string)
{
return btoa(input)
.trimBy("=") .trimBy("=")
.replace(/\+/g, '-') .replace(/\+/g, '-')
.replace(/\//g, '_'); .replace(/\//g, '_');
return `${this._api.REST}/system/apigateway/${encoded}/wopi/files/${this.curr_file.basename}&${this.access_token}`;
} }
private check_dirty():Promise<any> private check_dirty():Promise<any>
{ {

View File

@ -7,7 +7,7 @@
"author": "Dany LE", "author": "Dany LE",
"email": "contact@iohub.dev" "email": "contact@iohub.dev"
}, },
"version":"0.1.5-a", "version":"0.1.6-b",
"category":"Office", "category":"Office",
"icon":"icon.png", "icon":"icon.png",
"mimes":[ "mimes":[

View File

@ -6,7 +6,7 @@
"name": "batch", "name": "batch",
"data": { "data": {
"target": "release", "target": "release",
"modules": ["Blogger"] "modules": ["LibreOffice"]
} }
} }
] ]

View File

@ -1,15 +0,0 @@
# AntunnelTestClient
This is an example project, generated by AntOS Development Kit
## Howto
Use the Antedit command palette to access to the SDK functionalities:
1. Create new project
2. Init the project from the current folder located in side bar
3. Build and run the project
4. Release the project in zip package
## Set up build target
Open the `build.json` file from the current project tree and add/remove
build target entries and jobs. Save the file

Binary file not shown.

View File

@ -9,6 +9,9 @@ It support a wide range of documents.
![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true) ![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true)
## Change log ## Change log
- v 0.1.6-a:
* fix document exporting does not work
* fix missing toolbar icons
- v 0.1.5-a: - v 0.1.5-a:
* allow user to configure document server URI * allow user to configure document server URI
- v 0.1.4-a: - v 0.1.4-a:

Binary file not shown.

File diff suppressed because one or more lines are too long