From 1f318bcd00ba5cb26657050810c3f43cbdce5581 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Thu, 4 May 2017 13:15:42 +0200 Subject: Added functionality to list files transferred using urn:xmpp:filetransfer:http --- .../mod_http_upload_external.lua | 92 +++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'prosody-module') diff --git a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua index a9b4551..8ed7da1 100644 --- a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua +++ b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua @@ -34,6 +34,87 @@ module:add_extension(dataform { { name = "filetransfer-manager-ui-url", type = "text-single" }, }:form({ ["filetransfer-manager-ui-url"] = filetransfer_manager_ui_url }, "result")); +local function listfiles(origin, orig_from, stanza, request) + -- build the body + local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=list&user_jid=" .. orig_from; + -- the request + local respbody, statuscode = http.request(external_url, reqbody); + -- respbody is nil in case the server is not reachable + if respbody ~= nil then + respbody = string.gsub(respbody, "\\/", "/"); + end + + local filelistempty = true; + local list; + + -- check the response + if statuscode == 500 then + origin.send(st.error_reply(stanza, "cancel", "service-unavailable", respbody)); + return true; + elseif statuscode == 406 or statuscode == 400 or statuscode == 403 then + local errobj, pos, err = json.decode(respbody); + if err then + origin.send(st.error_reply(stanza, "wait", "internal-server-error", err)); + return true; + elseif errobj["err_code"] ~= nil and errobj["msg"] ~= nil then + if statuscode == 403 then + origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg)); + return true; + else + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "msg or err_code not found")); + return true; + end + end + elseif statuscode == 200 then + local respobj, pos, err = json.decode(respbody); + if err then + origin.send(st.error_reply(stanza, "wait", "internal-server-error", err)); + return true; + else + -- process json response + list = respobj.list; + filelistempty = list == nil or next(list) == nil; + end + else + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody)); + return true; + end + + local addedfiles = 0; + local reply = st.reply(stanza); + reply:tag("list", {xmlns=xmlns_http_upload}); + if filelistempty == false then + for i, file in ipairs(list) do + local url = file.url; + if url == "" then + url = nil; + end + local fileinfo = file.fileinfo; + local sender = file.sender_jid; + if sender == nil then + sender = ""; + end + local recipient = file.recipient_jid; + local sent_time = file.sent_time; + -- only add file if fileinfo is present + if fileinfo ~= nil then + addedfiles = addedfiles + 1; + reply:tag("file", {timestamp = tostring(sent_time), from = tostring(sender), to = recipient}); + reply:tag("url"):text(url):up(); + reply:tag("file-info"); + reply:tag("filename"):text(fileinfo.filename):up(); + reply:tag("size"):text(fileinfo.filesize):up(); + reply:tag("content-type"):text(fileinfo.content_type):up():up():up(); + end + end + end + if filelistempty or addedfiles == 0 then + reply:tag("empty"):up(); + end + origin.send(reply); + return true; +end + -- hooks module:hook("iq/host/"..xmlns_http_upload..":request", function (event) local stanza, origin = event.stanza, event.origin; @@ -70,10 +151,16 @@ module:hook("iq/host/"..xmlns_http_upload..":request", function (event) return true; end + local recipient = request.attr.recipient; + if not recipient then + origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing or invalid recipient")); + return true; + end + local content_type = request:get_child_text("content-type"); -- build the body - local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=upload&size=" .. filesize .. "&filename=" .. filename .. "&user_jid=" .. orig_from; + local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=upload&size=" .. filesize .. "&filename=" .. filename .. "&user_jid=" .. orig_from .. "&recipient_jid=" .. recipient; if content_type then reqbody = reqbody .. "&content_type=" .. content_type; end @@ -149,6 +236,7 @@ module:hook("iq/host/"..xmlns_http_upload..":request", function (event) else -- http file service not reachable origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode)); + return true; end local reply = st.reply(stanza); @@ -226,6 +314,8 @@ module:hook("iq/host/"..xmlns_http_upload..":request", function (event) reply:tag("slot", { xmlns = xmlns_http_upload }); reply:tag("deletetoken"):text(delete_token):up(); origin.send(reply); + elseif slot_type == "list" then + return listfiles(origin, orig_from, stanza, request); else origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody)); return true; -- cgit v1.2.3 From 14753b0d57eb0e6b679431b97064f8d335ebb867 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sat, 6 May 2017 14:09:20 +0200 Subject: prosody-module: Add functionality to delete a file based on a fileurl --- .../mod_http_upload_external.lua | 139 ++++++++++----------- 1 file changed, 69 insertions(+), 70 deletions(-) (limited to 'prosody-module') diff --git a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua index 8ed7da1..337b257 100644 --- a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua +++ b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua @@ -19,6 +19,7 @@ local st = require"util.stanza"; local http = require"socket.http"; local json = require"util.json"; local dataform = require "util.dataforms".new; +local ltn12 = require"ltn12"; -- depends module:depends("disco"); @@ -115,6 +116,72 @@ local function listfiles(origin, orig_from, stanza, request) return true; end +local function deletefile(origin, orig_from, stanza, request) + -- validate + local fileurl = request:get_child_text("fileurl"); + if not fileurl then + origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid fileurl")); + return true; + end + -- build the body + --local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=delete&file_url=" .. fileurl .. "&user_jid=" .. orig_from; + -- the request + local resp = {}; + local client, statuscode = http.request{url=fileurl, + sink=ltn12.sink.table(resp), + method="DELETE", + headers={["X-XMPP-SERVER-KEY"]=xmpp_server_key, + ["X-USER-JID"]=orig_from}}; + + local respbody = table.concat(resp); + -- respbody is nil in case the server is not reachable + if respbody ~= nil then + respbody = string.gsub(respbody, "\\/", "/"); + end + + -- check the response + if statuscode == 500 then + origin.send(st.error_reply(stanza, "cancel", "service-unavailable", respbody)); + return true; + elseif statuscode == 406 or statuscode == 400 or statuscode == 403 then + local errobj, pos, err = json.decode(respbody); + if err then + origin.send(st.error_reply(stanza, "wait", "internal-server-error", err)); + return true; + else + if statuscode == 403 and errobj["msg"] ~= nil then + origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg)); + return true; + elseif errobj["err_code"] ~= nil and errobj["msg"] ~= nil then + if errobj.err_code == 4 then + origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg) + :tag("missing-parameter", {xmlns=xmlns_http_upload}) + :text(errobj.parameters.missing_parameter)); + return true; + else + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "unknown err_code")); + return true; + end + else + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "msg or err_code not found")); + return true; + end + end + elseif statuscode == 204 then + local reply = st.reply(stanza); + reply:tag("deleted", { xmlns = xmlns_http_upload }); + origin.send(reply); + return true; + elseif respbody ~= nil then + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody)); + return true; + else + -- http file service not reachable + origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode)); + return true; + end +end + -- hooks module:hook("iq/host/"..xmlns_http_upload..":request", function (event) local stanza, origin = event.stanza, event.origin; @@ -244,81 +311,13 @@ module:hook("iq/host/"..xmlns_http_upload..":request", function (event) reply:tag("get"):text(get_url):up(); reply:tag("put"):text(put_url):up(); origin.send(reply); + return true; elseif slot_type == "delete" then - -- validate - local fileurl = request:get_child_text("fileurl"); - if not fileurl then - origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid fileurl")); - return true; - end - -- build the body - local reqbody = "xmpp_server_key=" .. xmpp_server_key .. "&slot_type=delete&file_url=" .. fileurl .. "&user_jid=" .. orig_from; - -- the request - local respbody, statuscode = http.request(external_url, reqbody); - -- respbody is nil in case the server is not reachable - if respbody ~= nil then - respbody = string.gsub(respbody, "\\/", "/"); - end - - local delete_token = nil; - -- check the response - if statuscode == 500 then - origin.send(st.error_reply(stanza, "cancel", "service-unavailable", respbody)); - return true; - elseif statuscode == 406 or statuscode == 400 or statuscode == 403 then - local errobj, pos, err = json.decode(respbody); - if err then - origin.send(st.error_reply(stanza, "wait", "internal-server-error", err)); - return true; - else - if errobj["err_code"] ~= nil and errobj["msg"] ~= nil then - if errobj.err_code == 4 then - origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg) - :tag("missing-parameter", {xmlns=xmlns_http_upload}) - :text(errobj.parameters.missing_parameter)); - return true; - else - origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "unknown err_code")); - return true; - end - elseif statuscode == 403 and errobj["msg"] ~= nil then - origin.send(st.error_reply(stanza, "cancel", "internal-server-error", errobj.msg)); - return true; - else - origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "msg or err_code not found")); - return true; - end - end - elseif statuscode == 200 then - local respobj, pos, err = json.decode(respbody); - if err then - origin.send(st.error_reply(stanza, "wait", "internal-server-error", err)); - return true; - else - if respobj["deletetoken"] ~= nil then - delete_token = respobj.deletetoken; - else - origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "deletetoken not found")); - return true; - end - end - elseif respbody ~= nil then - origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody)); - return true; - else - -- http file service not reachable - origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode)); - end - - local reply = st.reply(stanza); - reply:tag("slot", { xmlns = xmlns_http_upload }); - reply:tag("deletetoken"):text(delete_token):up(); - origin.send(reply); + return deletefile(origin, orig_from, stanza, request); elseif slot_type == "list" then return listfiles(origin, orig_from, stanza, request); else origin.send(st.error_reply(stanza, "cancel", "undefined-condition", "status code: " .. statuscode .. " response: " ..respbody)); return true; end - return true; end); -- cgit v1.2.3 From b317ffc7bfff772e83f8770e79218a30a14194f3 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sat, 6 May 2017 14:15:18 +0200 Subject: prosody-module: Only advertise 'filetransfer-manager-ui-url' if it is set --- .../mod_http_upload_external/mod_http_upload_external.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'prosody-module') diff --git a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua index 337b257..50f1f78 100644 --- a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua +++ b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua @@ -29,11 +29,13 @@ local xmlns_http_upload = "urn:xmpp:filetransfer:http"; module:add_feature(xmlns_http_upload); --- add additional disco info to advertise managing UI -module:add_extension(dataform { +if filetransfer_manager_ui_url then + -- add additional disco info to advertise managing UI + module:add_extension(dataform { { name = "FORM_TYPE", type = "hidden", value = xmlns_http_upload }, { name = "filetransfer-manager-ui-url", type = "text-single" }, -}:form({ ["filetransfer-manager-ui-url"] = filetransfer_manager_ui_url }, "result")); + }:form({ ["filetransfer-manager-ui-url"] = filetransfer_manager_ui_url }, "result")); +end local function listfiles(origin, orig_from, stanza, request) -- build the body -- cgit v1.2.3 From 16d3261f03b2d2ed9cd0b467fada388a207a1f67 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sat, 27 May 2017 20:31:32 +0200 Subject: prosody-module: treat empty file url also as invalid; treat status code 404 (not available) in case of deleting a file the same as 204 (deleted by this operation) --- prosody-module/mod_http_upload_external/mod_http_upload_external.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'prosody-module') diff --git a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua index 50f1f78..e2e0107 100644 --- a/prosody-module/mod_http_upload_external/mod_http_upload_external.lua +++ b/prosody-module/mod_http_upload_external/mod_http_upload_external.lua @@ -121,7 +121,7 @@ end local function deletefile(origin, orig_from, stanza, request) -- validate local fileurl = request:get_child_text("fileurl"); - if not fileurl then + if not fileurl or fileurl == '' then origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid fileurl")); return true; end @@ -169,7 +169,7 @@ local function deletefile(origin, orig_from, stanza, request) return true; end end - elseif statuscode == 204 then + elseif statuscode == 204 or statuscode == 404 then local reply = st.reply(stanza); reply:tag("deleted", { xmlns = xmlns_http_upload }); origin.send(reply); -- cgit v1.2.3