10
#include <libxml/nanohttp.h>
12
#include "tConfiguration.h"
13
#include "tDirectories.h"
14
#include "tResourceManager.h"
17
// server determined resource repository
18
tString tResourceManager::resRepoServer("http://resource.armagetronad.net/resource/");
19
// the nSettingItem is in gStuff.cpp
21
// client determined resource repository
22
tString tResourceManager::resRepoClient("http://resource.armagetronad.net/resource/");
23
static tSettingItem<tString> conf_res_repo("RESOURCE_REPOSITORY_CLIENT", tResourceManager::resRepoClient);
25
static int myHTTPFetch(const char *URI, const char *filename, const char *savepath)
32
con << tOutput( "$resource_downloading", URI );
33
// con << "Downloading " << URI << "...\n";
35
ctxt = xmlNanoHTTPOpen(URI, NULL);
37
con << "ERROR: ctxt is NULL\n";
41
if ( (rc = xmlNanoHTTPReturnCode(ctxt)) != 200 ) {
42
con << tOutput( rc == 404 ? "$resource_fetcherror_404" : "$resource_fetcherror", rc );
46
fd = fopen(savepath, "w");
48
xmlNanoHTTPClose(ctxt);
49
con << tOutput( "$resource_no_write", savepath );
53
//xmlNanoHTTPFetchContent( ctxt, &buf, &len );
55
buf = (char*)malloc(maxlen);
56
while( (len = xmlNanoHTTPRead(ctxt, buf, maxlen)) > 0 ) {
57
fwrite(buf, len, 1, fd);
61
xmlNanoHTTPClose(ctxt);
70
static int myFetch(const char *URIs, const char *filename, const char *savepath) {
71
const char *r = URIs, *p, *n;
75
// r = unprocessed data p = end-of-item + 1 u = item
76
// n = to-be r len = length of item savepath = result filepath
78
while (r[0] != '\0') {
79
while (r[0] == ' ') ++r; // skip spaces at the start of the item
80
(p = strchr(r, ';')) ? 0 : (p = strchr(r, '\0'));
81
n = (p[0] == '\0') ? p : (p + 1); // next item starts after the semicolon
82
// NOTE: skip semicolons, *NOT* nulls
83
while (p[-1] == ' ') --p; // skip spaces at the end of the item
84
len = (size_t)(p - r);
85
if (len > 0) { // skip this for null-length items
86
u = (char*)malloc((len + 1) * sizeof(char));
88
u[len] = '\0'; // u now contains the individual URI
89
rv = myHTTPFetch(u, filename, savepath); // TODO: handle other protocols?
91
if (rv == 0) return 0; // If successful, return the file retrieved
93
r = n; // move onto the next item
96
return rv; // last error
100
Allows for the fetching and caching of ressources available on the web,
101
such as maps (xml), texture (jpg, gif, bmp), sound and models.
102
Nota: On some forums (such as guru3.sytes.net), it is possible for the
103
download link not give information about the filename or type, ie:
104
http://guru3.sytes.net/download.php?id=1191. This is why the filename
105
parameter is required.
107
uri: The full uri to obtain the ressource
108
filename: The filename to use for the local ressource
109
Return a file handle to the ressource
110
NOTE: There must be *at least* one directory level, even if it is ./
112
tString tResourceManager::locateResource(const char *uri, const char *file) {
113
tString filepath, a_uri = tString(), savepath;
116
char * to_free = NULL; // string to delete later
119
char const *pos, *posb;
123
// Step 1: If 'file' has an open paren, cut everything after it off
124
if ( (pos = strchr(file, '(')) ) {
125
l = (size_t)(pos - file);
126
nf = (char*)malloc((l + 1) * sizeof(char));
127
strncpy(nf, file, l);
132
// Step 2: Extract URI, if any
134
if ( (posb = strchr(pos, ')')) ) {
135
l = (size_t)(posb - pos);
136
nf = (char*)malloc((l + 1) * sizeof(char));
144
// Validate paths and determine detination savepath
145
if (!file || file[0] == '\0') {
146
con << tOutput( "$resource_no_filename" );
147
return (tString) NULL;
149
if (file[0] == '/' || file[0] == '\\') {
150
con << tOutput( "$resource_abs_path" );
151
return (tString) NULL;
153
savepath = tDirectories::Resource().GetWritePath(file);
154
if (savepath == "") {
155
con << tOutput( "$resource_no_writepath" );
156
return (tString) NULL;
159
// Do we have this file locally ?
160
filepath = tDirectories::Resource().GetReadPath(file);
164
if ( NULL != to_free )
169
// Some sort of File not found
170
if (uri && strcmp("0", uri))
173
// add repositories to uri
174
if ( resRepoServer.Len() > 2 )
175
a_uri << resRepoServer << file << ';';
177
if ( resRepoClient.Len() > 2 && resRepoClient != resRepoServer )
178
a_uri << resRepoClient << file << ';';
180
con << tOutput( "$resource_not_cached", file );
182
rv = myFetch((const char *)a_uri, file, (const char *)savepath);
184
if ( NULL != to_free )
188
return (tString) NULL;
192
FILE* tResourceManager::openResource(const char *uri, const char *file) {
194
filepath = locateResource(uri, file);
195
if ( filepath.Len() <= 1 )
197
return fopen((const char *)filepath, "r");