1
0
Fork 0

Merge remote-tracking branch 'origin/devel' into devel

Conflicts:
	js/common/modules/org/arangodb/foxx.js
This commit is contained in:
Frank Celler 2013-03-23 23:48:48 +01:00
commit 4ccee5fe61
16 changed files with 397 additions and 58 deletions

View File

@ -31,6 +31,7 @@
"ERROR_CORRUPTED_CSV" : { "code" : 13, "message" : "csv is corrupt" }, "ERROR_CORRUPTED_CSV" : { "code" : 13, "message" : "csv is corrupt" },
"ERROR_FILE_NOT_FOUND" : { "code" : 14, "message" : "file not found" }, "ERROR_FILE_NOT_FOUND" : { "code" : 14, "message" : "file not found" },
"ERROR_CANNOT_WRITE_FILE" : { "code" : 15, "message" : "cannot write file" }, "ERROR_CANNOT_WRITE_FILE" : { "code" : 15, "message" : "cannot write file" },
"ERROR_CANNOT_OVERWRITE_FILE" : { "code" : 16, "message" : "cannot overwrite file" },
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" }, "ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
"ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" }, "ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" },
"ERROR_HTTP_NOT_FOUND" : { "code" : 404, "message" : "not found" }, "ERROR_HTTP_NOT_FOUND" : { "code" : 404, "message" : "not found" },

View File

@ -1,6 +1,6 @@
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */ /*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */
/*global require, module, Module, FS_MOVE, FS_REMOVE, FS_EXISTS, FS_IS_DIRECTORY, FS_IS_FILE, /*global require, module, Module, FS_MOVE, FS_REMOVE, FS_EXISTS, FS_IS_DIRECTORY, FS_IS_FILE,
FS_LIST_TREE, FS_UNZIP_FILE, FS_LIST_TREE, FS_UNZIP_FILE, FS_ZIP_FILE,
SYS_EXECUTE, SYS_LOAD, SYS_LOG, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STAT, SYS_RAND, SYS_EXECUTE, SYS_LOAD, SYS_LOG, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STAT, SYS_RAND,
SYS_READ, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, SYS_SHA256, SYS_WAIT, SYS_READ, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, SYS_SHA256, SYS_WAIT,
SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, PACKAGE_PATH, SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, PACKAGE_PATH,
@ -199,6 +199,11 @@
delete FS_UNZIP_FILE; delete FS_UNZIP_FILE;
} }
if (typeof FS_ZIP_FILE !== "undefined") {
internal.zipFile = FS_ZIP_FILE;
delete FS_ZIP_FILE;
}
if (typeof SYS_IMPORT_CSV_FILE !== "undefined") { if (typeof SYS_IMPORT_CSV_FILE !== "undefined") {
internal.importCsvFile = SYS_IMPORT_CSV_FILE; internal.importCsvFile = SYS_IMPORT_CSV_FILE;
delete SYS_IMPORT_CSV_FILE; delete SYS_IMPORT_CSV_FILE;

View File

@ -31,6 +31,7 @@
"ERROR_CORRUPTED_CSV" : { "code" : 13, "message" : "csv is corrupt" }, "ERROR_CORRUPTED_CSV" : { "code" : 13, "message" : "csv is corrupt" },
"ERROR_FILE_NOT_FOUND" : { "code" : 14, "message" : "file not found" }, "ERROR_FILE_NOT_FOUND" : { "code" : 14, "message" : "file not found" },
"ERROR_CANNOT_WRITE_FILE" : { "code" : 15, "message" : "cannot write file" }, "ERROR_CANNOT_WRITE_FILE" : { "code" : 15, "message" : "cannot write file" },
"ERROR_CANNOT_OVERWRITE_FILE" : { "code" : 16, "message" : "cannot overwrite file" },
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" }, "ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
"ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" }, "ERROR_HTTP_FORBIDDEN" : { "code" : 403, "message" : "forbidden" },
"ERROR_HTTP_NOT_FOUND" : { "code" : 404, "message" : "not found" }, "ERROR_HTTP_NOT_FOUND" : { "code" : 404, "message" : "not found" },

View File

@ -1,6 +1,6 @@
/*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */ /*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */
/*global require, module, Module, FS_MOVE, FS_REMOVE, FS_EXISTS, FS_IS_DIRECTORY, FS_IS_FILE, /*global require, module, Module, FS_MOVE, FS_REMOVE, FS_EXISTS, FS_IS_DIRECTORY, FS_IS_FILE,
FS_LIST_TREE, FS_UNZIP_FILE, FS_LIST_TREE, FS_UNZIP_FILE, FS_ZIP_FILE,
SYS_EXECUTE, SYS_LOAD, SYS_LOG, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STAT, SYS_RAND, SYS_EXECUTE, SYS_LOAD, SYS_LOG, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STAT, SYS_RAND,
SYS_READ, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, SYS_SHA256, SYS_WAIT, SYS_READ, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, SYS_SHA256, SYS_WAIT,
SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, PACKAGE_PATH, SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, PACKAGE_PATH,
@ -199,6 +199,11 @@
delete FS_UNZIP_FILE; delete FS_UNZIP_FILE;
} }
if (typeof FS_ZIP_FILE !== "undefined") {
internal.zipFile = FS_ZIP_FILE;
delete FS_ZIP_FILE;
}
if (typeof SYS_IMPORT_CSV_FILE !== "undefined") { if (typeof SYS_IMPORT_CSV_FILE !== "undefined") {
internal.importCsvFile = SYS_IMPORT_CSV_FILE; internal.importCsvFile = SYS_IMPORT_CSV_FILE;
delete SYS_IMPORT_CSV_FILE; delete SYS_IMPORT_CSV_FILE;

View File

@ -11,8 +11,8 @@
// FoxxApplication uses Underscore internally. This library is wonderful. // FoxxApplication uses Underscore internally. This library is wonderful.
var FoxxApplication, var FoxxApplication,
BaseMiddleware, baseMiddleware,
FormatMiddleware, formatMiddleware,
_ = require("underscore"), _ = require("underscore"),
db = require("org/arangodb").db, db = require("org/arangodb").db,
fs = require("fs"), fs = require("fs"),
@ -68,6 +68,8 @@ FoxxApplication = function (options) {
routes: [] routes: []
}; };
this.requires = {};
this.models = {};
this.helperCollection = {}; this.helperCollection = {};
if (_.isString(urlPrefix)) { if (_.isString(urlPrefix)) {
@ -77,9 +79,9 @@ FoxxApplication = function (options) {
if (_.isString(templateCollection)) { if (_.isString(templateCollection)) {
this.routingInfo.templateCollection = db._collection(templateCollection) || this.routingInfo.templateCollection = db._collection(templateCollection) ||
db._create(templateCollection); db._create(templateCollection);
myMiddleware = BaseMiddleware(templateCollection, this.helperCollection); myMiddleware = baseMiddleware(templateCollection, this.helperCollection);
} else { } else {
myMiddleware = BaseMiddleware(); myMiddleware = baseMiddleware();
} }
this.routingInfo.middleware = [ this.routingInfo.middleware = [
@ -105,9 +107,22 @@ _.extend(FoxxApplication.prototype, {
// Sometimes it is a good idea to actually start the application // Sometimes it is a good idea to actually start the application
// you wrote. If this precious moment has arrived, you should // you wrote. If this precious moment has arrived, you should
// use this function. // use this function.
start: function () { // You have to provide the start function with the `applicationContext`
// variable.
start: function (context, testMode) {
'use strict'; 'use strict';
var models = this.models,
requires = this.requires;
_.each(this.routingInfo.routes, function (route) {
route.action.context = context;
route.action.requires = requires;
route.action.models = models;
});
if (!testMode) {
db._collection("_routing").save(this.routingInfo); db._collection("_routing").save(this.routingInfo);
}
}, },
// The `handleRequest` method is the raw way to create a new // The `handleRequest` method is the raw way to create a new
@ -290,9 +305,9 @@ _.extend(FoxxApplication.prototype, {
this.helperCollection[name] = func; this.helperCollection[name] = func;
}, },
// ## Shortform for using the FormatMiddleware // ## Shortform for using the formatMiddleware
// //
// More information about the FormatMiddleware in the corresponding section. // More information about the formatMiddleware in the corresponding section.
// This is a shortcut to add the middleware to your application: // This is a shortcut to add the middleware to your application:
// //
// app.accepts(["json"], "json"); // app.accepts(["json"], "json");
@ -301,16 +316,16 @@ _.extend(FoxxApplication.prototype, {
this.routingInfo.middleware.push({ this.routingInfo.middleware.push({
url: { match: "/*" }, url: { match: "/*" },
action: { callback: new FormatMiddleware(allowedFormats, defaultFormat) } action: { callback: formatMiddleware(allowedFormats, defaultFormat) }
}); });
} }
}); });
// ## The Base Middleware // ## The Base Middleware
// The `BaseMiddleware` manipulates the request and response // The `baseMiddleware` manipulates the request and response
// objects to give you a nicer API. // objects to give you a nicer API.
BaseMiddleware = function (templateCollection, helperCollection) { baseMiddleware = function (templateCollection, helperCollection) {
'use strict'; 'use strict';
var middleware = function (request, response, options, next) { var middleware = function (request, response, options, next) {
var responseFunctions, var responseFunctions,
@ -471,11 +486,11 @@ BaseMiddleware = function (templateCollection, helperCollection) {
}; };
// ## The Format Middleware // ## The Format Middleware
// Unlike the `BaseMiddleware` this Middleware is only loaded if you // Unlike the `baseMiddleware` this Middleware is only loaded if you
// want it. This Middleware gives you Rails-like format handling via // want it. This Middleware gives you Rails-like format handling via
// the `extension` of the URL or the accept header. // the `extension` of the URL or the accept header.
// Say you request an URL like `/people.json`: // Say you request an URL like `/people.json`:
// The `FormatMiddleware` will set the format of the request to JSON // The `formatMiddleware` will set the format of the request to JSON
// and then delete the `.json` from the request. You can therefore write // and then delete the `.json` from the request. You can therefore write
// handlers that do not take an `extension` into consideration and instead // handlers that do not take an `extension` into consideration and instead
// handle the format via a simple String. // handle the format via a simple String.
@ -486,8 +501,8 @@ BaseMiddleware = function (templateCollection, helperCollection) {
// //
// Use it by calling: // Use it by calling:
// //
// FormatMiddleware = require('foxx').FormatMiddleware; // formatMiddleware = require('foxx').formatMiddleware;
// app.before("/*", FormatMiddleware.new(['json'])); // app.before("/*", formatMiddleware.new(['json']));
// //
// or the shortcut: // or the shortcut:
// //
@ -496,7 +511,7 @@ BaseMiddleware = function (templateCollection, helperCollection) {
// In both forms you can give a default format as a second parameter, // In both forms you can give a default format as a second parameter,
// if no format could be determined. If you give no `defaultFormat` this // if no format could be determined. If you give no `defaultFormat` this
// case will be handled as an error. // case will be handled as an error.
FormatMiddleware = function (allowedFormats, defaultFormat) { formatMiddleware = function (allowedFormats, defaultFormat) {
'use strict'; 'use strict';
var middleware, urlFormatToMime, mimeToUrlFormat, determinePathAndFormat; var middleware, urlFormatToMime, mimeToUrlFormat, determinePathAndFormat;
@ -571,10 +586,12 @@ FormatMiddleware = function (allowedFormats, defaultFormat) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
exports.loadManifest = function (path) { exports.loadManifest = function (path) {
var name; 'use strict';
var content; var name,
var manifest; content,
var key; manifest,
key,
app;
name = fs.join(path, "manifest.json"); name = fs.join(path, "manifest.json");
content = fs.read(name); content = fs.read(name);
@ -582,7 +599,7 @@ exports.loadManifest = function (path) {
for (key in manifest.apps) { for (key in manifest.apps) {
if (manifest.apps.hasOwnProperty(key)) { if (manifest.apps.hasOwnProperty(key)) {
var app = manifest.apps[key]; app = manifest.apps[key];
console.info("loading app '%s' from '%s'", key, app); console.info("loading app '%s' from '%s'", key, app);
@ -592,8 +609,8 @@ exports.loadManifest = function (path) {
}; };
exports.FoxxApplication = FoxxApplication; exports.FoxxApplication = FoxxApplication;
exports.BaseMiddleware = BaseMiddleware; exports.baseMiddleware = baseMiddleware;
//TODO: Make a String exports.FormatMiddleware = FormatMiddleware; //TODO: Make a String exports.formatMiddleware = formatMiddleware;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE // --SECTION-- END-OF-FILE

View File

@ -51,7 +51,7 @@ function CreateFoxxApplicationSpec () {
assertEqual(routingInfo.templateCollection, templateCollection); assertEqual(routingInfo.templateCollection, templateCollection);
}, },
testAdditionOfBaseMiddlewareInRoutingInfo: function () { testAdditionOfbaseMiddlewareInRoutingInfo: function () {
var app = new FoxxApplication(), var app = new FoxxApplication(),
routingInfo = app.routingInfo, routingInfo = app.routingInfo,
hopefully_base = routingInfo.middleware[0]; hopefully_base = routingInfo.middleware[0];
@ -191,11 +191,28 @@ function SetRoutesFoxxApplicationSpec () {
action = routes[0].action; action = routes[0].action;
assertEqual(routes.length, 1); assertEqual(routes.length, 1);
assertEqual(action.callback, myFuncString); assertEqual(action.callback, myFuncString);
},
testStart: function () {
var myFunc = function () {},
routes = app.routingInfo.routes;
app.requires = {
a: 1
};
app.models = {
b: 2
};
app.get('/simple/route', myFunc);
app.start("myContext", true);
assertEqual(app.routingInfo.routes[0].action.context, "myContext");
assertEqual(app.routingInfo.routes[0].action.requires.a, 1);
assertEqual(app.routingInfo.routes[0].action.models.b, 2);
} }
}; };
} }
/* TODO: Recreate the Test Suite, changed the Middlewares to Strings
function AddMidlewareFoxxApplicationSpec () { function AddMidlewareFoxxApplicationSpec () {
var app; var app;
@ -276,7 +293,7 @@ function AddMidlewareFoxxApplicationSpec () {
assertTrue(b); assertTrue(b);
}, },
testAddTheFormatMiddlewareUsingTheShortform: function () { testAddTheformatMiddlewareUsingTheShortform: function () {
// I wish I could mock like in Ruby :( This test is not really a test. // I wish I could mock like in Ruby :( This test is not really a test.
app.accepts(["json"], "json"); app.accepts(["json"], "json");
assertEqual(app.routingInfo.middleware.length, 2); assertEqual(app.routingInfo.middleware.length, 2);
@ -284,14 +301,13 @@ function AddMidlewareFoxxApplicationSpec () {
} }
}; };
} }
*/
function BaseMiddlewareWithoutTemplateSpec () { function baseMiddlewareWithoutTemplateSpec () {
var baseMiddleware, request, response, options, next; var baseMiddleware, request, response, options, next;
return { return {
setUp: function () { setUp: function () {
baseMiddleware = require("org/arangodb/foxx").BaseMiddleware(); baseMiddleware = require("org/arangodb/foxx").baseMiddleware();
request = {}; request = {};
response = {}; response = {};
options = {}; options = {};
@ -392,8 +408,8 @@ function BaseMiddlewareWithoutTemplateSpec () {
}; };
} }
function BaseMiddlewareWithTemplateSpec () { function baseMiddlewareWithTemplateSpec () {
var BaseMiddleware, request, response, options, next; var baseMiddleware, request, response, options, next;
return { return {
setUp: function () { setUp: function () {
@ -401,7 +417,7 @@ function BaseMiddlewareWithTemplateSpec () {
response = {}; response = {};
options = {}; options = {};
next = function () {}; next = function () {};
BaseMiddleware = require("org/arangodb/foxx").BaseMiddleware; baseMiddleware = require("org/arangodb/foxx").baseMiddleware;
}, },
testRenderingATemplate: function () { testRenderingATemplate: function () {
@ -417,7 +433,7 @@ function BaseMiddlewareWithTemplateSpec () {
templateLanguage: "underscore" templateLanguage: "underscore"
}); });
middleware = new BaseMiddleware(myCollection); middleware = new baseMiddleware(myCollection);
middleware(request, response, options, next); middleware(request, response, options, next);
response.render("simple/path", { username: "moonglum" }); response.render("simple/path", { username: "moonglum" });
@ -438,7 +454,7 @@ function BaseMiddlewareWithTemplateSpec () {
templateLanguage: "pirateEngine" templateLanguage: "pirateEngine"
}); });
middleware = new BaseMiddleware(myCollection); middleware = new baseMiddleware(myCollection);
middleware(request, response, options, next); middleware(request, response, options, next);
try { try {
@ -456,7 +472,7 @@ function BaseMiddlewareWithTemplateSpec () {
db._drop("templateTest"); db._drop("templateTest");
myCollection = db._create("templateTest"); myCollection = db._create("templateTest");
middleware = new BaseMiddleware(myCollection); middleware = new baseMiddleware(myCollection);
middleware(request, response, options, next); middleware(request, response, options, next);
try { try {
@ -476,7 +492,7 @@ function ViewHelperSpec () {
return { return {
setUp: function () { setUp: function () {
app = new FoxxApplication(); app = new FoxxApplication();
Middleware = require('org/arangodb/foxx').BaseMiddleware; Middleware = require('org/arangodb/foxx').baseMiddleware;
request = {}; request = {};
response = {}; response = {};
options = {}; options = {};
@ -516,12 +532,12 @@ function ViewHelperSpec () {
}; };
} }
function FormatMiddlewareSpec () { function formatMiddlewareSpec () {
var Middleware, middleware, request, response, options, next; var Middleware, middleware, request, response, options, next;
return { return {
setUp: function () { setUp: function () {
Middleware = require('org/arangodb/foxx').FormatMiddleware; Middleware = require('org/arangodb/foxx').formatMiddleware;
request = {}; request = {};
response = {}; response = {};
options = {}; options = {};
@ -632,9 +648,10 @@ function FormatMiddlewareSpec () {
jsunity.run(CreateFoxxApplicationSpec); jsunity.run(CreateFoxxApplicationSpec);
jsunity.run(SetRoutesFoxxApplicationSpec); jsunity.run(SetRoutesFoxxApplicationSpec);
//jsunity.run(AddMidlewareFoxxApplicationSpec); //jsunity.run(AddMidlewareFoxxApplicationSpec);
//jsunity.run(BaseMiddlewareWithoutTemplateSpec); //jsunity.run(baseMiddlewareWithoutTemplateSpec);
//jsunity.run(BaseMiddlewareWithTemplateSpec); //jsunity.run(baseMiddlewareWithTemplateSpec);
//jsunity.run(ViewHelperSpec); //jsunity.run(ViewHelperSpec);
//jsunity.run(FormatMiddlewareSpec); // TODO: Recreate the Test Suite, changed the Middlewares to Strings
//jsunity.run(formatMiddlewareSpec);
return jsunity.done(); return jsunity.done();

View File

@ -18,6 +18,7 @@ ERROR_OUT_OF_MEMORY_MMAP,12,"out of memory in mmap","Will be raised when there i
ERROR_CORRUPTED_CSV,13,"csv is corrupt","Will be raised when encountering a corrupt csv line." ERROR_CORRUPTED_CSV,13,"csv is corrupt","Will be raised when encountering a corrupt csv line."
ERROR_FILE_NOT_FOUND,14,"file not found","Will be raised when a file is not found." ERROR_FILE_NOT_FOUND,14,"file not found","Will be raised when a file is not found."
ERROR_CANNOT_WRITE_FILE,15,"cannot write file","Will be raised when a file cannot be written." ERROR_CANNOT_WRITE_FILE,15,"cannot write file","Will be raised when a file cannot be written."
ERROR_CANNOT_OVERWRITE_FILE,16,"cannot overwrite file","Will be raised when an attempt is made to overwrite an existing file."
################################################################################ ################################################################################
## HTTP standard errors ## HTTP standard errors

View File

@ -41,6 +41,7 @@
#include "BasicsC/conversions.h" #include "BasicsC/conversions.h"
#include "BasicsC/hashes.h"
#include "BasicsC/locks.h" #include "BasicsC/locks.h"
#include "BasicsC/logging.h" #include "BasicsC/logging.h"
#include "BasicsC/string-buffer.h" #include "BasicsC/string-buffer.h"
@ -1517,6 +1518,62 @@ char* TRI_HomeDirectory () {
#endif #endif
////////////////////////////////////////////////////////////////////////////////
/// @brief calculate the crc32 checksum of a file
////////////////////////////////////////////////////////////////////////////////
int TRI_Crc32File (char const* path, uint32_t* crc) {
FILE* fin;
void* buffer;
size_t bufferSize;
int res;
*crc = TRI_InitialCrc32();
bufferSize = 4096;
buffer = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, bufferSize, false);
if (buffer == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
fin = fopen(path, "rb");
if (fin == NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer);
return TRI_ERROR_FILE_NOT_FOUND;
}
res = TRI_ERROR_NO_ERROR;
while (true) {
int sizeRead = (int) fread(buffer, 1, bufferSize, fin);
if (sizeRead < bufferSize) {
if (feof(fin) == 0) {
res = errno;
break;
}
}
if (sizeRead > 0) {
*crc = TRI_BlockCrc32(*crc, buffer, sizeRead);
}
else if (sizeRead <= 0) {
break;
}
}
fclose(fin);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer);
*crc = TRI_FinalCrc32(*crc);
return res;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @} /// @}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -246,6 +246,12 @@ char* TRI_LocateBinaryPath (char const* argv0);
char* TRI_HomeDirectory (void); char* TRI_HomeDirectory (void);
////////////////////////////////////////////////////////////////////////////////
/// @brief calculate the crc32 checksum of a file
////////////////////////////////////////////////////////////////////////////////
int TRI_Crc32File (char const*, uint32_t*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @} /// @}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -27,6 +27,7 @@ void TRI_InitialiseErrorMessages (void) {
REG_ERROR(ERROR_CORRUPTED_CSV, "csv is corrupt"); REG_ERROR(ERROR_CORRUPTED_CSV, "csv is corrupt");
REG_ERROR(ERROR_FILE_NOT_FOUND, "file not found"); REG_ERROR(ERROR_FILE_NOT_FOUND, "file not found");
REG_ERROR(ERROR_CANNOT_WRITE_FILE, "cannot write file"); REG_ERROR(ERROR_CANNOT_WRITE_FILE, "cannot write file");
REG_ERROR(ERROR_CANNOT_OVERWRITE_FILE, "cannot overwrite file");
REG_ERROR(ERROR_HTTP_BAD_PARAMETER, "bad parameter"); REG_ERROR(ERROR_HTTP_BAD_PARAMETER, "bad parameter");
REG_ERROR(ERROR_HTTP_FORBIDDEN, "forbidden"); REG_ERROR(ERROR_HTTP_FORBIDDEN, "forbidden");
REG_ERROR(ERROR_HTTP_NOT_FOUND, "not found"); REG_ERROR(ERROR_HTTP_NOT_FOUND, "not found");

View File

@ -43,6 +43,8 @@ extern "C" {
/// Will be raised when a file is not found. /// Will be raised when a file is not found.
/// - 15: @LIT{cannot write file} /// - 15: @LIT{cannot write file}
/// Will be raised when a file cannot be written. /// Will be raised when a file cannot be written.
/// - 16: @LIT{cannot overwrite file}
/// Will be raised when an attempt is made to overwrite an existing file.
/// - 400: @LIT{bad parameter} /// - 400: @LIT{bad parameter}
/// Will be raised when the HTTP request does not fulfill the requirements. /// Will be raised when the HTTP request does not fulfill the requirements.
/// - 403: @LIT{forbidden} /// - 403: @LIT{forbidden}
@ -550,6 +552,16 @@ void TRI_InitialiseErrorMessages (void);
#define TRI_ERROR_CANNOT_WRITE_FILE (15) #define TRI_ERROR_CANNOT_WRITE_FILE (15)
////////////////////////////////////////////////////////////////////////////////
/// @brief 16: ERROR_CANNOT_OVERWRITE_FILE
///
/// cannot overwrite file
///
/// Will be raised when an attempt is made to overwrite an existing file.
////////////////////////////////////////////////////////////////////////////////
#define TRI_ERROR_CANNOT_OVERWRITE_FILE (16)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief 400: ERROR_HTTP_BAD_PARAMETER /// @brief 400: ERROR_HTTP_BAD_PARAMETER
/// ///

View File

@ -27,8 +27,9 @@
#include "zip.h" #include "zip.h"
#include "files.h" #include "BasicsC/files.h"
#include "Zip/unzip.h" #include "Zip/unzip.h"
#include "Zip/zip.h"
#ifdef _WIN32 #ifdef _WIN32
#define USEWIN32IOAPI #define USEWIN32IOAPI
@ -123,7 +124,7 @@ static int ExtractCurrentFile (unzFile uf,
*(filenameWithoutPath - 1) = c; *(filenameWithoutPath - 1) = c;
// try again // try again
fout = fopen(writeFilename,"wb"); fout = fopen(fullPath, "wb");
} }
TRI_Free(TRI_CORE_MEM_ZONE, fullPath); TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
@ -137,6 +138,7 @@ static int ExtractCurrentFile (unzFile uf,
if (result < 0) { if (result < 0) {
fclose(fout); fclose(fout);
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
@ -144,7 +146,7 @@ static int ExtractCurrentFile (unzFile uf,
if (fwrite(buffer, result, 1, fout) != 1) { if (fwrite(buffer, result, 1, fout) != 1) {
fclose(fout); fclose(fout);
return errno; return TRI_set_errno(TRI_ERROR_SYS_ERROR);
} }
} }
else { else {
@ -211,6 +213,136 @@ static int UnzipFile (unzFile uf,
/// @{ /// @{
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief zips a file
////////////////////////////////////////////////////////////////////////////////
int TRI_ZipFile (const char* filename,
TRI_vector_string_t const* files,
const char* password) {
void* buffer;
size_t bufferSize;
zipFile zf;
#ifdef USEWIN32IOAPI
zlib_filefunc64_def ffunc;
#endif
size_t i, n;
int res;
if (TRI_ExistsFile(filename)) {
return TRI_ERROR_CANNOT_OVERWRITE_FILE;
}
bufferSize = 16384;
buffer = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, bufferSize, false);
if (buffer == NULL) {
return TRI_ERROR_OUT_OF_MEMORY;
}
#ifdef USEWIN32IOAPI
fill_win32_filefunc64A(&ffunc);
zf = zipOpen2_64(filename, 0, NULL, &ffunc);
#else
zf = zipOpen64(filename, 0);
#endif
if (zf == NULL) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer);
return ZIP_ERRNO;
}
res = TRI_ERROR_NO_ERROR;
n = files->_length;
for (i = 0; i < n; ++i) {
FILE* fin;
char* file;
char* saveName;
zip_fileinfo zi;
uint32_t crc;
int isLarge;
file = TRI_AtVectorString(files, i);
memset(&zi, 0, sizeof(zi));
res = TRI_Crc32File(file, &crc);
if (res != TRI_ERROR_NO_ERROR) {
break;
}
isLarge = (TRI_SizeFile(file) > 0xFFFFFFFFLL);
saveName = file;
while (*saveName == '\\' || *saveName == '/') {
++saveName;
}
if (zipOpenNewFileInZip3_64(zf,
saveName,
&zi,
NULL,
0,
NULL,
0,
NULL, /* comment*/
Z_DEFLATED,
Z_DEFAULT_COMPRESSION,
0,
-MAX_WBITS,
DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY,
password,
(unsigned long) crc,
isLarge) != ZIP_OK) {
}
fin = fopen(file, "rb");
if (fin == NULL) {
break;
}
while (true) {
int sizeRead;
sizeRead = (int) fread(buffer, 1, bufferSize, fin);
if (sizeRead < bufferSize) {
if (feof(fin) == 0) {
res = TRI_set_errno(TRI_ERROR_SYS_ERROR);
break;
}
}
if (sizeRead > 0) {
res = zipWriteInFileInZip(zf, buffer, sizeRead);
if (res != 0) {
break;
}
}
else if (sizeRead <= 0) {
break;
}
}
fclose(fin);
zipCloseFileInZip(zf);
if (res != TRI_ERROR_NO_ERROR) {
break;
}
}
zipClose(zf, NULL);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, buffer);
return res;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief unzips a file /// @brief unzips a file
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -33,6 +33,7 @@
#endif #endif
#include "BasicsC/common.h" #include "BasicsC/common.h"
#include "BasicsC/vector.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -47,6 +48,14 @@ extern "C" {
/// @{ /// @{
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief zips a file
////////////////////////////////////////////////////////////////////////////////
int TRI_ZipFile (const char*,
TRI_vector_string_t const*,
const char*);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief unzips a file /// @brief unzips a file
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -95,7 +95,8 @@ lib_libarango_a_SOURCES = \
lib/Utilities/LineEditor.cpp \ lib/Utilities/LineEditor.cpp \
lib/Utilities/ScriptLoader.cpp \ lib/Utilities/ScriptLoader.cpp \
lib/Zip/ioapi.c \ lib/Zip/ioapi.c \
lib/Zip/unzip.c lib/Zip/unzip.c \
lib/Zip/zip.c
################################################################################ ################################################################################
### @brief library "libarango.a", client part ### @brief library "libarango.a", client part

View File

@ -604,12 +604,15 @@ static v8::Handle<v8::Value> JS_ListTree (v8::Arguments const& argv) {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a file of any type or directory exists /// @brief unzips a file
/// ///
/// @FUN{fs.exists(@FA{path})} /// @FUN{fs.unzip(@FA{filename}, @FA{outpath}, @FA{skipPaths}, @FA{overwrite}, @FA{password})}
/// ///
/// Returns true if a file (of any type) or a directory exists at a given /// Unzips the zip file specified by @FA{filename} into the path specified by
/// path. If the file is a broken symbolic link, returns false. /// @FA{outpath}. Overwrites any existing target files if @FA{overwrite} is set
/// to @LIT{true}.
///
/// Returns @LIT{true} if the file was unzipped successfully.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_UnzipFile (v8::Arguments const& argv) { static v8::Handle<v8::Value> JS_UnzipFile (v8::Arguments const& argv) {
@ -644,6 +647,76 @@ static v8::Handle<v8::Value> JS_UnzipFile (v8::Arguments const& argv) {
} }
int res = TRI_UnzipFile(filename.c_str(), outPath.c_str(), skipPaths, overwrite, p); int res = TRI_UnzipFile(filename.c_str(), outPath.c_str(), skipPaths, overwrite, p);
if (res == TRI_ERROR_NO_ERROR) {
return scope.Close(v8::True());
}
return scope.Close(v8::ThrowException(v8::String::New(TRI_errno_string(res))));
}
////////////////////////////////////////////////////////////////////////////////
/// @brief zips a file
///
/// @FUN{fs.zip(@FA{filename}, @FA{files})
///
/// Stores the files specified by @FA{files} in the zip file @FA{filename}.
///
/// Returns @LIT{true} if the file was zipped successfully.
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ZipFile (v8::Arguments const& argv) {
v8::HandleScope scope;
// extract arguments
if (argv.Length() < 2 || argv.Length() > 3) {
return scope.Close(v8::ThrowException(v8::String::New("usage: zip(<filename>, <files>, <password>)")));
}
const string filename = TRI_ObjectToString(argv[0]);
if (! argv[1]->IsArray()) {
return scope.Close(v8::ThrowException(v8::String::New("usage: zip(<filename>, <files>, <password>)")));
}
v8::Handle<v8::Array> files = v8::Handle<v8::Array>::Cast(argv[1]);
int res = TRI_ERROR_NO_ERROR;
TRI_vector_string_t filenames;
TRI_InitVectorString(&filenames, TRI_UNKNOWN_MEM_ZONE);
for (uint32_t i = 0 ; i < files->Length(); ++i) {
v8::Handle<v8::Value> file = files->Get(i);
if (file->IsString()) {
string fname = TRI_ObjectToString(file);
TRI_PushBackVectorString(&filenames, TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, fname.c_str()));
}
else {
res = TRI_ERROR_BAD_PARAMETER;
break;
}
}
if (res != TRI_ERROR_NO_ERROR) {
TRI_ClearVectorString(&filenames);
TRI_DestroyVectorString(&filenames);
return scope.Close(v8::ThrowException(v8::String::New("usage: zip(<filename>, <files>, <password>)")));
}
const char* p;
string password;
if (argv.Length() == 3) {
password = TRI_ObjectToString(argv[2]);
p = password.c_str();
}
else {
p = NULL;
}
res = TRI_ZipFile(filename.c_str(), &filenames, p);
TRI_ClearVectorString(&filenames);
TRI_DestroyVectorString(&filenames);
if (res == TRI_ERROR_NO_ERROR) { if (res == TRI_ERROR_NO_ERROR) {
return scope.Close(v8::True()); return scope.Close(v8::True());
} }
@ -1847,6 +1920,7 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "FS_MOVE", JS_Move); TRI_AddGlobalFunctionVocbase(context, "FS_MOVE", JS_Move);
TRI_AddGlobalFunctionVocbase(context, "FS_REMOVE", JS_Remove); TRI_AddGlobalFunctionVocbase(context, "FS_REMOVE", JS_Remove);
TRI_AddGlobalFunctionVocbase(context, "FS_UNZIP_FILE", JS_UnzipFile); TRI_AddGlobalFunctionVocbase(context, "FS_UNZIP_FILE", JS_UnzipFile);
TRI_AddGlobalFunctionVocbase(context, "FS_ZIP_FILE", JS_ZipFile);
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute); TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute);
TRI_AddGlobalFunctionVocbase(context, "SYS_GETLINE", JS_Getline); TRI_AddGlobalFunctionVocbase(context, "SYS_GETLINE", JS_Getline);

View File

@ -186,7 +186,7 @@ typedef struct
#include "crypt.h" #include "crypt.h"
#endif #endif
local linkedlist_datablock_internal* allocate_new_datablock() local linkedlist_datablock_internal* allocate_new_datablock(void)
{ {
linkedlist_datablock_internal* ldi; linkedlist_datablock_internal* ldi;
ldi = (linkedlist_datablock_internal*) ldi = (linkedlist_datablock_internal*)
@ -1506,12 +1506,12 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in
return err; return err;
} }
extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong _crc32)
{ {
return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); return zipCloseFileInZipRaw64 (file, uncompressed_size, _crc32);
} }
extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong _crc32)
{ {
zip64_internal* zi; zip64_internal* zi;
ZPOS64_T compressed_size; ZPOS64_T compressed_size;
@ -1599,7 +1599,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
if (!zi->ci.raw) if (!zi->ci.raw)
{ {
crc32 = (uLong)zi->ci.crc32; _crc32 = (uLong)zi->ci.crc32;
uncompressed_size = zi->ci.totalUncompressedData; uncompressed_size = zi->ci.totalUncompressedData;
} }
compressed_size = zi->ci.totalCompressedData; compressed_size = zi->ci.totalCompressedData;
@ -1618,7 +1618,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
} }
zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ zip64local_putValue_inmemory(zi->ci.central_header+16,_crc32,4); /*crc*/
if(compressed_size >= 0xffffffff) if(compressed_size >= 0xffffffff)
@ -1709,7 +1709,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
err = ZIP_ERRNO; err = ZIP_ERRNO;
if (err==ZIP_OK) if (err==ZIP_OK)
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,_crc32,4); /* crc 32, unknown */
if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
{ {