-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
1,317 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
pipeline: | ||
build: | ||
image: metwork/mfcom-${OS_VERSION}-buildimage:integration | ||
commands: | ||
- /opt/metwork-mfext/bin/mfext_wrapper layer_wrapper --layers=mapserver@mfext -- make MAPSERVER_LIB_DIR=/opt/metwork-mfext/opt/mapserver/lib PREFIX=/opt/metwork-mfext/opt/mapserver clean all test install | ||
|
||
matrix: | ||
OS_VERSION: | ||
- centos6 | ||
- centos7 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
## What is it ? | ||
|
||
This is a tiny C library to invoke [mapserver](http://mapserver.org) engine | ||
as a library (with no daemon or CGI). | ||
|
||
## Build | ||
|
||
### Prerequisites | ||
|
||
- mapserver installed | ||
- standard compilation tools (gcc, make...) | ||
- glib2 library and corresponding headers | ||
|
||
### Building | ||
|
||
To build the library you must specify: | ||
|
||
- `MAPSERVER_LIB_DIR`: the full path of the directory containing `libmapserver.so` | ||
- `PREFIX`: the full path of the directory where you want to install the library | ||
|
||
For example: | ||
|
||
``` | ||
make MAPSERVER_LIB_DIR=/opt/mapserver/lib PREFIX=/usr/local clean all install | ||
``` | ||
|
||
### Testing | ||
|
||
You must have `valgrind` tool installed. | ||
|
||
``` | ||
make MAPSERVER_LIB_DIR=/opt/mapserver/lib PREFIX=/usr/local test | ||
``` | ||
|
||
## Usage | ||
|
||
### Compilation flags | ||
|
||
The library use `pkg-config` tool. So you can use the following command to | ||
get the compilation flags: | ||
|
||
``` | ||
pkg-config --cflags --libs mapserverapi | ||
``` | ||
|
||
If not found, you may have to add `PREFIX` at the end of `${PKG_CONFIG_PATH}` | ||
environnement variable. | ||
|
||
### In your code | ||
|
||
```C | ||
#include <mapserverapi.h> | ||
|
||
// [...] | ||
|
||
# Init the library (mandatory) | ||
mapserverapi_init(); | ||
|
||
gchar *mapfile_content; | ||
# [...] | ||
# Put a mapfile content into mapfile_content string | ||
|
||
# Set a WMS query_string (for this example) | ||
gchar *query_string = "LAYERS=ocean&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_xml&SRS=EPSG%3A4326&BBOX=-180.0,-90.0,180.0,90.0&WIDTH=500&HEIGHT=250" | ||
|
||
# Invoke mapserver | ||
void *body; | ||
gchar *content_type = NULL; | ||
gsize body_length; | ||
gboolean b = mapserverapi_invoke(mapfile_content, query_string, &body, &content_type, &body_length); | ||
if (b == TRUE) { | ||
# you have the full body (PNG image in this example) in body variable (this buffer is managed by the library, don't free it by yourself !) | ||
# you have the body length in body_length variable. | ||
# you have the content_type of the body in content_type variable (you have to free it after use). | ||
|
||
# [...] | ||
|
||
# free content_type when you have finished with them | ||
# (but don't free body variable) | ||
g_free(content_type); | ||
} | ||
|
||
# Another way to use the library, invoke mapserver and get the body in a file | ||
gchar *content_type2 = NULL; | ||
gboolean | ||
|
||
# Destroy the library | ||
mapserverapi_destroy(); | ||
``` | ||
### Uninstalling | ||
``` | ||
make MAPSERVER_LIB_DIR=/opt/mapserver/lib PREFIX=/usr/local uninstall | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
all: | ||
cd src && $(MAKE) all | ||
|
||
clean: | ||
cd src && $(MAKE) clean | ||
|
||
test: | ||
cd src && $(MAKE) test | ||
|
||
install: | ||
cd src && $(MAKE) install |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
ifndef MAPSERVER_LIB_DIR | ||
$(error MAPSERVER_LIB_DIR is not set, see README.md file) | ||
endif | ||
ifndef PREFIX | ||
$(error PREFIX is not set, see README.md file) | ||
endif | ||
|
||
_LDFLAGS=$(LDFLAGS) -L. $(shell pkg-config --libs glib-2.0) -L$(MAPSERVER_LIB_DIR) -L$(PREFIX)/lib -lmapserver | ||
_CFLAGS=$(CFLAGS) -I. $(shell pkg-config --cflags glib-2.0) -I$(PREFIX)/include -fPIC -Wall | ||
CC=gcc | ||
|
||
OBJECTS=random.o mapserverapi.o | ||
BINARIES=libmapserverapi.so test_mapserverapi | ||
|
||
all: $(OBJECTS) $(BINARIES) mapserverapi.pc | ||
|
||
clean: | ||
rm -f $(OBJECTS) $(BINARIES) core.* vgcore.* testresult.png mapserverapi.pc | ||
|
||
mapserverapi.pc: mapserverapi.pc.pc | ||
cat $< |sed 's~@@@PREFIX@@@~$(PREFIX)~g' |sed 's~@@@MAPSERVER_LIB_DIR@@@~$(MAPSERVER_LIB_DIR)~g' >$@ | ||
|
||
random.o: random.c random.h | ||
$(CC) -c $(_CFLAGS) -o $@ $< | ||
|
||
mapserverapi.o: mapserverapi.c mapserverapi.h | ||
$(CC) -c $(_CFLAGS) -o $@ $< | ||
|
||
test_mapserverapi: test_mapserverapi.c $(OBJECTS) | ||
$(CC) $(_CFLAGS) $(_LDFLAGS) -o $@ $^ | ||
|
||
libmapserverapi.so: $(OBJECTS) | ||
$(CC) -shared $(_CFLAGS) $(_LDFLAGS) -o $@ $^ | ||
|
||
install: all | ||
if ! test -d $(PREFIX)/lib/pkgconfig; then mkdir -p $(PREFIX)/lib/pkgconfig; fi | ||
if ! test -d $(PREFIX)/include; then mkdir -p $(PREFIX)/include; fi | ||
cp -f libmapserverapi.so $(PREFIX)/lib/ | ||
cp -f mapserverapi.h $(PREFIX)/include/ | ||
cp -f mapserverapi.pc $(PREFIX)/lib/pkgconfig/ | ||
|
||
uninstall: | ||
rm -f $(PREFIX)/lib/libmapserverapi.so | ||
rm -f $(PREFIX)/include/mapserverapi.h | ||
rm -f $(PREFIX)/lib/pkgconfig/mapserverapi.pc | ||
|
||
test: all | ||
valgrind --show-possibly-lost=no --leak-check=full ./test_mapserverapi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#ifndef MAPSERVERAPI_MAPSERVER_H_ | ||
#define MAPSERVERAPI_MAPSERVER_H_ | ||
|
||
int msCGIHandler(const char *query_string, void **out_buffer, size_t *buffer_length); | ||
void msIO_resetHandlers(void); | ||
|
||
#endif /* MAPSERVERAPI_MAPSERVER_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
#include "mapserverapi.h" | ||
#include <glib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#include "random.h" | ||
#include "mapserver.h" | ||
|
||
static gboolean __MAPSERVERAPI_INITIALIZED = FALSE; | ||
static gchar *__MAPSERVERAPI_TMPDIR = NULL; | ||
|
||
void mapserverapi_init() { | ||
if (__MAPSERVERAPI_INITIALIZED) { | ||
g_critical("mapserverapi already initialized: call mapserverapi_destroy() before"); | ||
g_assert(__MAPSERVERAPI_INITIALIZED == FALSE); | ||
} | ||
__MAPSERVERAPI_INITIALIZED = TRUE; | ||
const gchar *tmp; | ||
tmp = g_getenv("MAPSERVERAPI_TMPDIR"); | ||
if (tmp != NULL) { | ||
__MAPSERVERAPI_TMPDIR = g_strdup(tmp); | ||
return; | ||
} | ||
tmp = g_getenv("TMPDIR"); | ||
if (tmp != NULL) { | ||
__MAPSERVERAPI_TMPDIR = g_strdup(tmp); | ||
return; | ||
} | ||
tmp = g_getenv("TMP"); | ||
if (tmp != NULL) { | ||
__MAPSERVERAPI_TMPDIR = g_strdup(tmp); | ||
return; | ||
} | ||
__MAPSERVERAPI_TMPDIR = g_strdup("/tmp"); | ||
} | ||
|
||
void mapserverapi_destroy() { | ||
if (__MAPSERVERAPI_INITIALIZED == FALSE) { | ||
g_critical("mapserverapi not initialized: call mapserverapi_init() before"); | ||
g_assert(__MAPSERVERAPI_INITIALIZED == TRUE); | ||
} | ||
msIO_resetHandlers(); | ||
__MAPSERVERAPI_INITIALIZED = FALSE; | ||
g_free(__MAPSERVERAPI_TMPDIR); | ||
} | ||
|
||
gchar *get_tmpfilename() { | ||
gchar *unique = get_unique_hexa_identifier(); | ||
gchar *tmp = g_strdup_printf("%s/mapserverapi_%s.map", __MAPSERVERAPI_TMPDIR, | ||
unique); | ||
g_free(unique); | ||
return tmp; | ||
} | ||
|
||
void assert_mapserverapi_initialized() { | ||
if (__MAPSERVERAPI_INITIALIZED == FALSE) { | ||
g_critical("mapserverapi not initialized: call mapserverapi_init() before use"); | ||
g_assert(__MAPSERVERAPI_INITIALIZED); | ||
} | ||
} | ||
|
||
gboolean mapserverapi_invoke(const gchar *mapfile_content, const gchar *query_string, void **body, | ||
gchar **content_type, gsize *body_length) { | ||
assert_mapserverapi_initialized(); | ||
g_assert(mapfile_content != NULL); | ||
g_assert(body != NULL); | ||
g_assert(query_string != NULL); | ||
g_assert(strlen(query_string) > 0); | ||
gboolean res; | ||
gchar *mapfile_path = get_tmpfilename(); | ||
res = g_file_set_contents(mapfile_path, mapfile_content, -1, NULL); | ||
if (!res) { | ||
g_critical("can't write mapfile in %s", mapfile_path); | ||
g_free(mapfile_path); | ||
return FALSE; | ||
} | ||
GString *gs = g_string_new(NULL); | ||
g_string_append_printf(gs, "MAP=%s", mapfile_path); | ||
gs = g_string_append_c(gs, '&'); | ||
if (query_string[0] == '?') { | ||
gs = g_string_append(gs, query_string + sizeof(gchar)); | ||
} else { | ||
gs = g_string_append(gs, query_string); | ||
} | ||
gchar *mapserver_qs = g_string_free(gs, FALSE); | ||
int mapserver_status; | ||
void *mapserver_buffer; | ||
size_t mapserver_buffer_length; | ||
res = TRUE; | ||
g_debug("Calling mapserver with query_string[%s]...", mapserver_qs); | ||
mapserver_status = msCGIHandler(mapserver_qs, &mapserver_buffer, &mapserver_buffer_length); | ||
unlink(mapfile_path); | ||
g_free(mapfile_path); | ||
if (mapserver_status != 0) { | ||
g_warning("bad reply from mapserver for query_string = %s", mapserver_qs); | ||
res = FALSE; | ||
} | ||
if (mapserver_buffer_length < 14) { | ||
g_warning("bad reply from mapserver for query_string = %s (no Content-Type)", mapserver_qs); | ||
g_free(mapserver_qs); | ||
return FALSE; | ||
} | ||
if (strncasecmp((const char*) mapserver_buffer, "Content-type: ", 14) != 0) { | ||
g_warning("bad reply from mapserver for query_string = %s (no Content-Type)", mapserver_qs); | ||
g_free(mapserver_qs); | ||
return FALSE; | ||
} | ||
int end_of_ct = 13; | ||
while ((end_of_ct + 1 < mapserver_buffer_length) && (((char*)mapserver_buffer)[end_of_ct + 1] != 10)) { | ||
end_of_ct++; | ||
} | ||
if (end_of_ct + 1 == mapserver_buffer_length) { | ||
g_warning("bad reply from mapserver for query_string = %s (bad Content-Type)", query_string); | ||
g_free(mapserver_qs); | ||
return FALSE; | ||
} | ||
int start_of_data = end_of_ct + 2; | ||
while ((start_of_data < mapserver_buffer_length) && (((char*)mapserver_buffer)[start_of_data] != 10)) { | ||
start_of_data++; | ||
} | ||
if (start_of_data == mapserver_buffer_length) { | ||
g_warning("bad reply from mapserver for query_string = %s (corrupt Content-Type)", mapserver_qs); | ||
g_free(mapserver_qs); | ||
return FALSE; | ||
} | ||
start_of_data++; | ||
gchar *ct = g_malloc((end_of_ct - 14 + 2) * sizeof(gchar)); | ||
memcpy(ct, mapserver_buffer + 14 * sizeof(gchar), sizeof(gchar) * (end_of_ct - 14 + 2)); | ||
ct[end_of_ct - 14 + 1] = '\0'; | ||
if (content_type != NULL) { | ||
*content_type = g_strstrip(ct); | ||
} else { | ||
g_free(ct); | ||
} | ||
if (body != NULL) { | ||
*body = mapserver_buffer + start_of_data * sizeof(gchar); | ||
} | ||
if (body_length != NULL) { | ||
*body_length = mapserver_buffer_length - start_of_data; | ||
} | ||
g_free(mapserver_qs); | ||
return res; | ||
} | ||
|
||
gchar *mapserverapi_invoke_to_file(const gchar *mapfile_content, const gchar *query_string, | ||
const gchar *target_file) { | ||
void *body = NULL; | ||
gsize body_length; | ||
gchar *tmp_content_type = NULL; | ||
gboolean res = mapserverapi_invoke(mapfile_content, query_string, &body, | ||
&tmp_content_type, &body_length); | ||
if (res == FALSE) { | ||
return NULL; | ||
} | ||
GError *error = NULL; | ||
gboolean res2 = g_file_set_contents(target_file, body, body_length, &error); | ||
if (res2 == FALSE) { | ||
g_warning("can't write mapserver output to target_file: %s", target_file); | ||
if (error != NULL) { | ||
g_warning("error message: %s", error->message); | ||
} | ||
g_free(tmp_content_type); | ||
return NULL; | ||
} | ||
return tmp_content_type; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef MAPSERVERAPI_H_ | ||
#define MAPSERVERAPI_H_ | ||
|
||
#include <glib.h> | ||
|
||
void mapserverapi_init(); | ||
void mapserverapi_destroy(); | ||
gboolean mapserverapi_invoke(const gchar *mapfile_content, const gchar *query_string, void **body, gchar **content_type, gsize *body_length); | ||
gchar *mapserverapi_invoke_to_file(const gchar *mapfile_content, const gchar *query_string, const gchar *target_file); | ||
|
||
#endif /* MAPSERVERAPI_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
prefix=@@@PREFIX@@@@ | ||
exec_prefix=@@@PREFIX@@@ | ||
libdir=@@@PREFIX@@@/lib | ||
includedir=@@@PREFIX@@@/include | ||
|
||
Name: mapserverapi | ||
Description: tiny library to invoke mapserver as a library | ||
Version: 0.1.0 | ||
Requires: glib-2.0 gobject-2.0 gthread-2.0 | ||
Libs: -L$(libdir) -lmapserverapi -L@@@MAPSERVER_LIB_DIR@@@ -lmapserver | ||
Cflags: -I$(includedir) |
Oops, something went wrong.