Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: issues #328

Merged
merged 15 commits into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ cmdline: ## run SIPI inside Docker (does not compile)
@mkdir -p ${PWD}/images
docker run -it --rm -v ${PWD}:/sipi --workdir "/sipi" --expose "1024" --expose "1025" -p 1024:1024 -p 1025:1025 dhlabbasel/sipi-base:18.04 /bin/sh

.PHONY: cmdline-debug
cmdline-debug: ## run SIPI inside Docker (does not compile)
@mkdir -p ${PWD}/images
docker run -it --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --rm -v ${PWD}:/sipi --workdir "/sipi" --expose "1024" --expose "1025" -p 1024:1024 -p 1025:1025 dhlabbasel/sipi-base:18.04 /bin/sh

.PHONY: clean
clean: ## cleans the project directory
@rm -rf build-linux/
Expand Down
5 changes: 5 additions & 0 deletions config/sipi.config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -273,5 +273,10 @@ routes = {
method = 'GET',
route = '/api/token',
script = 'token.lua'
},
{
method = 'GET',
route = '/test/luafunctions',
script = 'test_functions.lua'
}
}
2 changes: 1 addition & 1 deletion docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
To build Sipi from source code, you must have
[Kakadu](http://kakadusoftware.com/), a JPEG 2000 development toolkit
that is not provided with Sipi and must be licensed separately. The
Kakadu source code archive `v7_A_7-01382N.zip` must be placed in the
Kakadu source code archive `v8_0_5-01727L.zip` must be placed in the
`vendor` subdirectory of the source tree before building Sipi.

Sipi's build process requires [CMake](https://cmake.org/) (minimal
Expand Down
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ C++ and runs on Linux (including [Debian](https://www.debian.org/),
[Ubuntu](https://www.ubuntu.com/), and
[CentOS](https://www.centos.org/)) and Mac OS X.

Freely distributable binary releases are available.
Freely distributable binary releases are available
[here](https://hub.docker.com/repository/docker/daschswiss/knora-sipi) as docker image.
34 changes: 34 additions & 0 deletions docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Simple Image Presentation Interface (SIPI) - Introduction

SIPI has a threefold usage:

- it can act as a standard [IIIF](https://iiif.io) server
- implementing the IIIF Image API V3 level2
- implementing the IIIF Authentication API
- implementing an extension to provaide access to multiple page PDF's using the IIIF URL syntax
- implementing a simple web server
- serving HTML and other files
- providing embeded [LUA](https://www.lua.org) scripting
- providing embeded sqlite3 with LUA interface
- configurable routing for RESTful services programmed in LUA
- acting as a stand-alone image conversion tool
- from/to TIFF, JPEG200, PNG, JPEG, (PDF)
- preserving embedded metadata (EXIF, IPTC, TIFF, XMP)
- preserving and/or converting ICC color profiles

## SIPI as IIIF-Server
### Extensions to the IIIF-Standard

#### Access to PDF Pages
SIPI is able to deliver PDF's using an extended IIIF-URL to access a specific page of a multipage PDF.
- info.json includes a field `numpages` that indicates the total number of pages
the PDF has
- the image-ID given in the IIIF URL must incude a pagenumber specificer
`@pagenum` with an integer between 1 and the maximum number of pages, e.g.
```
https://iiif.dummy.org/images/test.pdf@12/full/,1000/default.jpg
```
The given URL would return page #12 of the PDF `test.pdf` with a hight of 1000 pixels.
Thus, all IIIF URL parts will work as expected.


18 changes: 17 additions & 1 deletion docs/lua.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,18 @@ path is known. The second form can be used for uploads by passing the
file index. It returns `true, table` on success or `false, errormsg` on
failure. The table has 2 members: - `mimetype` - `charset`

### server.file\_mimeconsistency

success, is_consistent = server.file_mimeconsistency(path)
success, is_consistent = server.file_mimeconsistency(index)

Checks if the file extension and the mimetype determined by the magic
of the file is consistent. The first form requires a path (including the
filename with extension), the second can be used for checking uploads by
passing the file index. It returns `true, is_consistent` on success or
`false, errormsg` in case of an error. `is_consistent` is true if the
mimetype corresponds to the file extension.

### server.requireAuth

success, table = server.requireAuth()
Expand Down Expand Up @@ -437,14 +449,18 @@ Example:

### server.copyTmpfile

success, errormsg = server.copyTmpfile()
success, errormsg = server.copyTmpfile(from, to)

Sipi saves each uploaded file in a temporary location (given by the
config variable `tmpdir`) and deletes it after the request has been
served. This function is used to copy the file to another location where
it can be retrieved later. Returns `true, nil` on success or
`false, errormsg` on failure.

Parameters:
- `from`: an index (integer value) of array server.uploads.
- `target`: an absolute path

### server.systime

systime = server.systime()
Expand Down
4 changes: 3 additions & 1 deletion include/SipiImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class SipiImageError : public std::exception {
SkipMetadata skip_metadata; //!< If true, all metadata is stripped off

public:
static std::unordered_map<std::string, std::string> mimetypes; //! format (key) to mimetype (value) conversion map
//
/*!
* Default constructor. Creates an empty image
*/
Expand Down Expand Up @@ -224,8 +224,10 @@ class SipiImageError : public std::exception {
* Checks if the actual mimetype of an image file corresponds to the indicated mimetype and the extension of the filename.
* This function is used to check if information submitted with a file are actually valid.
*/
/* ToDo: Delete
static bool checkMimeTypeConsistency(const std::string &path, const std::string &given_mimetype,
const std::string &filename);
*/

/*!
* Getter for nx
Expand Down
146 changes: 146 additions & 0 deletions scripts/test_functions.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
--
-- Copyright © 2016 Lukas Rosenthaler, Andrea Bianco, Benjamin Geer,
-- Ivan Subotic, Tobias Schweizer, André Kilchenmann, and André Fatton.
-- This file is part of Sipi.
-- Sipi is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published
-- by the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
-- Sipi is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- Additional permission under GNU AGPL version 3 section 7:
-- If you modify this Program, or any covered work, by linking or combining
-- it with Kakadu (or a modified version of that library), containing parts
-- covered by the terms of the Kakadu Software Licence, the licensors of this
-- Program grant you additional permission to convey the resulting work.
-- See the GNU Affero General Public License for more details.
-- You should have received a copy of the GNU Affero General Public
-- License along with Sipi. If not, see <http://www.gnu.org/licenses/>.

require "send_response"

-- Sample values for Content-Type that should parse correctly.

local html_utf8 = {
mimetype = "text/html",
charset = "utf-8"
}

local html_no_charset = {
mimetype = "text/html",
charset = nil
}

local mimetype_test_data = {
{
received = "text/html;charset=utf-8",
expected = html_utf8
},
{
received = "text/html;charset=UTF-8",
expected = html_utf8
},
{
received = "Text/HTML;Charset=\"utf-8\"",
expected = html_utf8
},
{
received = "text/html; charset=\"utf-8\"",
expected = html_utf8
},
{
received = "text/html",
expected = html_no_charset
}
}

local bad_mimetype = ";;"

success, errmsg = server.setBuffer()

if not success then
server.log("server.setBuffer() failed: " .. errmsg, server.loglevel.LOG_ERR)
send_error(500, "buffer could not be set correctly")
return
end

result = {}

for i, test_data_item in ipairs(mimetype_test_data) do
local success, parsed_mimetype = server.parse_mimetype(test_data_item.received)

if not success then
send_error(400, "Couldn't parse mimetype: " .. test_data_item.received)
return -1
end

if parsed_mimetype == nil then
send_error(400, "With input '" .. test_data_item.received .. "', parsed mimetype is nil")
return -1
end

if parsed_mimetype.mimetype ~= test_data_item.expected.mimetype then
send_error(400, "With input '" .. test_data_item.received .. "', parsed mimetype is '" .. parsed_mimetype.mimetype .. "' but should be '" .. test_data_item.expected.mimetype .. "'")
return -1
end

if parsed_mimetype.charset ~= test_data_item.expected.charset then
send_error(400, "With input '" .. test_data_item.received .. "', parsed charset is '" .. (parsed_mimetype.charset or "") .. "' but should be '" .. (test_data_item.expected.charset or "") .. "'")
return -1
end

table.insert(result, { test_data_item, "OK" })
end

-- Try parsing a mimetype that should return an error.

local success, parsed_bad_mimetype = server.parse_mimetype(bad_mimetype)

if success then
send_error(400, "MIME type '" .. bad_mimetype .. "' parsed, but should have caused an error")
return -1
else
table.insert(result, { { received = bad_mimetype, expected = "error" }, "OK" })
end

-- Check mimetypes of files

local test_files = {
{
filename = 'big.pdf',
expected_mimetype = "application/pdf"
},
{
filename = 'test.csv',
expected_mimetype = "text/plain"
}
}

for i, fileitem in ipairs(test_files) do
local success, mimetype = server.file_mimetype(config.imgroot .. "/" .. fileitem.filename)
if not success then
send_error(400, "Couldn't get mimetype: " .. mimetype)
return -1
end

if mimetype.mimetype ~= fileitem.expected_mimetype then
send_error(400, "File has '" .. mimetype.mimetype .. "', but expected '" .. fileitem.expected_mimetype .. "'!")
return -1
end
table.insert(result, { {filename = fileitem.filename, mimetype = mimetype}, "OK" })
end

for i, fileitem in ipairs(test_files) do
local tmpname = config.imgroot .. "/" .. fileitem.filename
local success, is_ok = server.file_mimeconsistency(tmpname, fileitem.expected_mimetype, fileitem.filename)
if not success then
send_error(400, is_ok)
-- send_error(400, "Couldn't get mimetype consistency: " .. is_ok)
return -1
end

table.insert(result, { {filename = fileitem.filename, is_ok = (is_ok and "OK" or "NOT OK") }, "OK" })
end

send_success(result)
19 changes: 14 additions & 5 deletions scripts/test_sqlite.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,27 @@ require "send_response"

function test_db()
local db = sqlite("./db/test.db", "RW")
local qry = db << "SELECT * FROM image WHERE id = ?"
local id = 512
local row = qry(id);
return row[1]
--local qry = db << "SELECT * FROM image WHERE id < ? ORDER BY id"
local qry = db << "SELECT * FROM image WHERE id = ?1 OR id = ?2 ORDER BY id"
local result = {}
local row = qry(1024, 512)
while row do
result[row[0]] = row[1]
row = qry()
end
qry = ~qry
db = ~db
return result
end

function err (x)
server.send_error(500, x)
return false
end

local status, res = xpcall(test_db, err)
--local status, res = xpcall(test_db, err)
res = test_db()
status = true
if not status then
send_error(500, res)
return false
Expand Down
Loading