local arg = ... ulib = require("ulib") sqlite = modules.sqlite() vfs = require("vfs") local handle = {} local docpath = nil local dbpath = nil local result = function(data) return { error = false, result = data } end local error = function(data) return { error = data, result = false } end local mkdirp =function(p) if not vfs.exists(p) then if not vfs.mkdir(p) then return false, error("Unable to create directory: "..p) end end return true, nil end local merge_files = function(data) local firstfile = data.file[1] local fpath = docpath.."/"..data.cid local r, e = mkdirp(fpath) if not r then return e end fpath = fpath.."/"..os.date("%d-%m-%Y_%H_%M_%S")..".pdf" -- concat the files if #data.file > 1 then local cmd = "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="..vfs.ospath(fpath) for i,v in ipairs(data.file) do cmd = cmd.." \""..vfs.ospath(v).."\"" end os.execute(cmd) if not vfs.exists(fpath) then return error("Unable to merge PDF files") end cmd = "chmod 777 "..vfs.ospath(fpath) os.execute(cmd) else local cmd = "mv \""..vfs.ospath(firstfile).."\" \""..vfs.ospath(fpath).."\"" os.execute(cmd) if not vfs.exists(fpath) then return error("Unable to move PDF file") end end -- move the thumb file to the cache folder local thumb = docpath.."/cache/"..std.sha1(firstfile:gsub(docpath, ""))..".png" local desthumb = docpath.."/cache/"..std.sha1(fpath:gsub(docpath, ""))..".png" if vfs.exists(thumb) then vfs.move(thumb, desthumb) end -- remove all other thumb files for i,v in ipairs(data.file) do thumb = docpath.."/cache/"..std.sha1(v:gsub(docpath, ""))..".png" if vfs.exists(thumb) then vfs.delete(thumb) end -- delete all files if vfs.exists(v) then vfs.delete(v) end end return result(fpath) end handle.init = function(args) local r, e = mkdirp(docpath) if not r then return e end r, e = mkdirp(docpath.."/unclassified") if not r then return e end r, e = mkdirp(docpath.."/cache") if not r then return e end local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to initialized database "..dbpath) end local sql -- check if table exists if sqlite.hasTable(db, "categories") == 0 then -- create the table sql = [[ CREATE TABLE "categories" ( "id" INTEGER, "name" TEXT NOT NULL, PRIMARY KEY("id" AUTOINCREMENT) ); ]] if sqlite.query(db, sql) ~= 1 then sqlite.dbclose(db) return error("Unable to create table categories") end -- insert unknown category sql = [[ INSERT INTO categories("id","name") VALUES (0,'Uncategoried'); ]] if sqlite.query(db, sql) ~= 1 then sqlite.dbclose(db) return error("Unable to create default category") end end if sqlite.hasTable(db, "owners") == 0 then -- create the table sql = [[ CREATE TABLE "owners" ( "id" INTEGER, "name" TEXT NOT NULL, PRIMARY KEY("id" AUTOINCREMENT) ); ]] if sqlite.query(db, sql) ~= 1 then sqlite.dbclose(db) return error("Unable to create table owners") end -- insert unknown category sql = [[ INSERT INTO owners("id","name") VALUES (0,'None'); ]] if sqlite.query(db, sql) ~= 1 then sqlite.dbclose(db) return error("Unable to create default None owner") end end if sqlite.hasTable(db, "docs") == 0 then -- create the table sql = [[ CREATE TABLE "docs" ( "id" INTEGER, "name" TEXT NOT NULL, "ctime" INTEGER, "day" INTEGER, "month" INTEGER, "year" INTEGER, "cid" INTEGER DEFAULT 0, "oid" INTEGER DEFAULT 0, "file" TEXT NOT NULL, "tags" TEXT, "note" TEXT, "mtime" INTEGER, FOREIGN KEY("oid") REFERENCES "owners"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, FOREIGN KEY("cid") REFERENCES "categories"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, PRIMARY KEY("id" AUTOINCREMENT) ); ]] if sqlite.query(db, sql) ~= 1 then sqlite.dbclose(db) return error("Unable to create table docs") end end sqlite.dbclose(db) return result("Docify initialized") end handle.select = function(param) local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local r = sqlite.select(db, param.table, "*", param.cond) sqlite.dbclose(db) if r == nil then return error("Unable to select data from "..param.table) else return result(r) end end handle.fetch = function(table) local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local r = sqlite.select(db, table, "*", "1=1") sqlite.dbclose(db) if r == nil then return error("Unable to fetch data from "..table) else return result(r) end end handle.insert = function(param) local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local keys = {} local values = {} for k,v in pairs(param.data) do if k ~= "id" then table.insert(keys,k) if type(v) == "number" then table.insert(values, v) elseif type(v) == "boolean" then table.insert( values, v and 1 or 0 ) else local t = "\""..v:gsub('"', '""').."\"" table.insert(values,t) end end end local sql = "INSERT INTO "..param.table.." ("..table.concat(keys,',')..') VALUES (' sql = sql..table.concat(values,',')..');' local r = sqlite.query(db, sql) sqlite.dbclose(db) if r == nil then return error("Unable to insert data to "..param.table) else return result("Data inserted") end end handle.preview = function(path) -- convert -resize 300x500 noel.pdf[0] thumb.png local name = std.sha1(path:gsub(docpath,""))..".png" -- try to find the thumb local tpath = docpath.."/cache/"..name if not vfs.exists(tpath) then -- regenerate thumb local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath) os.execute(cmd) end if vfs.exists(tpath) then local cmd = "chmod 777 "..vfs.ospath(tpath) os.execute(cmd) return result(tpath) else return error("do not exist") end end handle.get_doc = function(id) local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local r = sqlite.select(db, "docs", "*", "id = "..id) if r == nil or #r == 0 then sqlite.dbclose(db) return error("Unable to select data from "..param.table) else r = r[1] local ret, meta = vfs.fileinfo(r.file) if ret then r.fileinfo = meta end local o = sqlite.select(db, "owners", "*", "id = "..r.oid) sqlite.dbclose(db) if o == nil or #o == 0 then return result(r) else o = o[1] r.owner = o.name if r.ctime then r.ctime = os.date("%d/%m/%Y %H:%M:%S", r.ctime) end if r.mtime then r.mtime = os.date("%d/%m/%Y %H:%M:%S", r.mtime) end local edate = "" return result(r) end end end handle.deletedoc = function(param) local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local sql = "DELETE FROM docs WHERE id="..param.id..";" local ret = sqlite.query(db, sql) == 1 sqlite.dbclose(db) if not ret then return error("Unable to delete doc meta-data from database") end -- move file to unclassified local newfile = docpath.."/unclassified/"..std.basename(param.file) vfs.move(param.file, newfile) -- delete thumb file local thumb = docpath.."/cache/"..std.sha1(param.file:gsub(docpath,""))..".png" if vfs.exists(thumb) then vfs.delete(thumb) end return result("Document entry deleted") end handle.updatedoc = function(param) local r = merge_files(param.data) if r.error then return r end if param.rm then -- move ve the old file to unclassified local newfile = docpath.."/unclassified/"..std.basename(param.rm) local cmd = "rm -f "..vfs.ospath(param.rm) os.execute(cmd) --if vfs.exists(param.rm) then -- vfs.move(param.rm, newfile) --end -- move the thumb file if needed local thumb = docpath.."/cache/"..std.sha1(param.rm:gsub(docpath,""))..".png" local newwthumb = docpath.."/cache/"..std.sha1(newfile:gsub(docpath, ""))..".png" if vfs.exists(thumb) then vfs.move(thumb, newwthumb) end end param.data.file = r.result print(r.result) param.data.mtime = os.time(os.date("!*t")) return handle.update({ table = "docs", data = param.data }) end handle.insertdoc = function(data) local r = merge_files(data) if r.error then return r end -- save data data.file = r.result data.ctime = os.time(os.date("!*t")) data.mtime = os.time(os.date("!*t")) local ret = handle.insert({ table = "docs", data = data }) return ret end handle.update = function(param) if not param.data.id or param.data.id == 0 then return error("Record id is 0 or not found") end local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local lst = {} for k,v in pairs(param.data) do if(type(v)== "number") then table.insert(lst,k.."="..v) elseif type(v) == "boolean" then table.insert( lst, k.."="..(v and 1 or 0) ) else table.insert(lst,k.."=\""..v:gsub('"', '""').."\"") end end local sql = "UPDATE "..param.table.." SET "..table.concat(lst,",").." WHERE id="..param.data.id..";" local r = sqlite.query(db, sql) sqlite.dbclose(db) if r == nil then return error("Unable to update data to "..param.table) else return result("Data Updated") end end handle.delete = function(param) if param.id == 0 then return error("Record with id = 0 cannot be deleted") end local db = sqlite._getdb(vfs.ospath(dbpath)) if not db then return error("Unable to get database "..dbpath) end local sql = "DELETE FROM "..param.table.." WHERE id="..param.id..";" local r = sqlite.query(db, sql) sqlite.dbclose(db) if r == nil then return error("Unable to delete data from "..param.table) else return result("Data deleted") end end handle.printdoc = function(opt) local cmd = "lp " if opt.printer and opt.printer ~= "" then cmd = cmd .. " -d "..opt.printer end if opt.side == 0 then cmd = cmd.. " -o sides=one-sided" elseif opt.side == 1 then cmd = cmd.. " -o sides=two-sided-long-edge" elseif opt.side == 2 then cmd = cmd .. " -o sides=two-sided-short-edge" end -- orientation landscape if opt.orientation == 1 then cmd = cmd.." -o orientation-requested=5" end if opt.range == 1 then cmd = cmd.." -P "..opt.pages end cmd = cmd.. " "..vfs.ospath(opt.file) print(cmd) os.execute(cmd) return result("A print job has been posted on server. Check if it successes") end if arg.action and handle[arg.action] then -- check if the database exits docpath = arg.docpath dbpath = docpath.."/docify.db" return handle[arg.action](arg.args) else return error("Invalid action parameter") end