Jelajahi Sumber

Renamed files to have a consistent name scheme.

mingodad 13 tahun lalu
induk
melakukan
28fbb7123c
6 mengubah file dengan 3645 tambahan dan 0 penghapusan
  1. 150 0
      ext/sq_base64.cpp
  2. 1032 0
      ext/sq_fpdf.cpp
  3. 848 0
      ext/sq_fs.c
  4. 165 0
      ext/sq_mix.cpp
  5. 1275 0
      ext/sq_mongoose.cpp
  6. 175 0
      ext/sq_zlib.cpp

+ 150 - 0
ext/sq_base64.cpp

@@ -0,0 +1,150 @@
+/*
+* lbase64.c
+* base64 encoding and decoding for Lua 5.1
+* Luiz Henrique de Figueiredo <[email protected]>
+* 27 Jun 2007 19:04:40
+* This code is hereby placed in the public domain.
+* Ported to Squrrel by Domingo Alvarez Duarte
+*/
+
+#include "squirrel.h"
+#include <string.h>
+#include "sqstdblobimpl.h"
+
+#define MYNAME		_SC("base64")
+#define MYVERSION	_SC(MYNAME " library for " LUA_VERSION " / Jun 2007")
+
+#define uint unsigned int
+
+static const char code[]=
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static void encode(SQBlob &b, uint c1, uint c2, uint c3, int n)
+{
+    unsigned long tuple=c3+256UL*(c2+256UL*c1);
+    int i;
+    char s[4];
+    for (i=0; i<4; i++)
+    {
+        s[3-i] = code[tuple % 64];
+        tuple /= 64;
+    }
+    for (i=n+1; i<4; i++) s[i]='=';
+    b.Write(s,4);
+}
+
+static SQRESULT base64_encode(HSQUIRRELVM v)		/** encode(s) */
+{
+    SQInteger l;
+    const unsigned char *s;
+    SQRESULT rc;
+    if((rc = sq_getstr_and_size(v,2, (const char **)&s, &l)) != SQ_OK) return rc;
+    SQBlob b(0, l*2);
+    int n;
+    for (n=l/3; n--; s+=3) encode(b,s[0],s[1],s[2],3);
+    switch (l%3)
+    {
+    case 1:
+        encode(b,s[0],0,0,1);
+        break;
+    case 2:
+        encode(b,s[0],s[1],0,2);
+        break;
+    }
+    sq_pushstring(v, (SQChar*)b.GetBuf(), b.Len());
+    return 1;
+}
+
+static void decode(SQBlob &b, int c1, int c2, int c3, int c4, int n)
+{
+    unsigned long tuple=c4+64L*(c3+64L*(c2+64L*c1));
+    char s[3];
+    switch (--n)
+    {
+    case 3:
+        s[2]=tuple;
+    case 2:
+        s[1]=tuple >> 8;
+    case 1:
+        s[0]=tuple >> 16;
+    }
+    b.Write(s,n);
+}
+
+static SQRESULT base64_decode(HSQUIRRELVM v)		/** decode(s) */
+{
+    SQInteger l;
+    const unsigned char *s;
+    SQRESULT rc;
+    if((rc = sq_getstr_and_size(v,2, (const char **)&s, &l)) != SQ_OK) return rc;
+    SQBlob b(0, l*2);
+    int n=0;
+    char t[4];
+    for (;;)
+    {
+        int c=*s++;
+        switch (c)
+        {
+            const char *p;
+        default:
+            p=strchr(code,c);
+            if (p==NULL) return 0;
+            t[n++]= p-code;
+            if (n==4)
+            {
+                decode(b,t[0],t[1],t[2],t[3],4);
+                n=0;
+            }
+            break;
+        case '=':
+            switch (n)
+            {
+            case 1:
+                decode(b,t[0],0,0,0,1);
+                break;
+            case 2:
+                decode(b,t[0],t[1],0,0,2);
+                break;
+            case 3:
+                decode(b,t[0],t[1],t[2],0,3);
+                break;
+            }
+        case 0:
+            sq_pushstring(v, (SQChar*)b.GetBuf(), b.Len());
+            return 1;
+        case '\n':
+        case '\r':
+        case '\t':
+        case ' ':
+        case '\f':
+        case '\b':
+            break;
+        }
+    }
+    return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),base64_##name,nparams,tycheck}
+static SQRegFunction base64_methods[] =
+{
+    _DECL_FUNC(encode,2,_SC(".s")),
+    _DECL_FUNC(decode,2,_SC(".s")),
+    {0,0}
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_base64(HSQUIRRELVM v)
+    {
+        sq_pushstring(v,_SC("base64"),-1);
+        sq_newclass(v,SQFalse);
+        sq_insert_reg_funcs(v, base64_methods);
+        sq_newslot(v,-3,SQTrue);
+        return 1;
+    }
+
+#ifdef __cplusplus
+}
+#endif

+ 1032 - 0
ext/sq_fpdf.cpp

@@ -0,0 +1,1032 @@
+#include "squirrel.h"
+#include "fpdf.h"
+#include <string.h>
+#include <stdio.h>
+
+class Sq_Fpdf : public FPDF {
+    protected:
+        HSQUIRRELVM sqvm;
+        HSQOBJECT self_weakref;
+    public:
+    Sq_Fpdf(HSQUIRRELVM v, HSQOBJECT &self):FPDF(){
+        sqvm = v;
+        self_weakref = self;
+    }
+
+    void callVirtual(const SQChar *func_name){
+        //sq_reservestack(sqvm, 20);
+        SQInteger top = sq_gettop(sqvm);
+        sq_pushobject(sqvm, self_weakref);
+        sq_pushstring(sqvm, func_name, -1);
+        sq_get(sqvm, -2);
+        if(sq_gettype(sqvm, -1) == OT_CLOSURE){
+            sq_push(sqvm, -2); //this
+            sq_call(sqvm, 1, SQFalse, SQTrue);
+        }
+        sq_settop(sqvm, top);
+    }
+
+    void Header (){
+        callVirtual(_SC("Header"));
+    };
+    void Footer () {
+        callVirtual(_SC("Footer"));
+    };
+    bool AcceptPageBreak (){
+        callVirtual(_SC("AcceptPageBreak"));
+        return FPDF::AcceptPageBreak();
+    };
+};
+
+static SQRESULT sq_glue_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	Sq_Fpdf *self = ((Sq_Fpdf *)p);
+	delete self;
+	return 1;
+}
+
+static SQRESULT sq_glue_constructor(HSQUIRRELVM v)
+{
+    //SQ_FUNC_VARS_NO_TOP(v);
+    HSQOBJECT self;
+    sq_resetobject(&self);
+    sq_getstackobj(v, 1, &self);
+
+	Sq_Fpdf *cptr = new Sq_Fpdf(v, self);
+    sq_setinstanceup(v, 1, cptr);
+    sq_setreleasehook(v,1, sq_glue_releasehook);
+	return 1;
+}
+
+SQ_OPT_STRING_STRLEN();
+
+static const SQChar *SQ_FPDF_TAG = "Sq_Fpdf";
+
+#define GET_SQ_FPDF() SQ_GET_INSTANCE(v, 1, Sq_Fpdf, SQ_FPDF_TAG)
+
+/* bool AcceptPageBreak(  ) */
+static SQRESULT sq_glue_AcceptPageBreak(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushbool(v, self->FPDF::AcceptPageBreak());
+	return 1;
+}
+
+/* void AddFont( char const * afamily , char const * astyle  = 0 , char const * afile  = 0 ) */
+static SQRESULT sq_glue_AddFont(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, afamily);
+	SQ_OPT_STRING(v, 3, astyle, 0);
+	SQ_OPT_STRING(v, 4, afile, 0);
+	self->AddFont(afamily, astyle, afile);
+	return 0;
+}
+
+/* int AddLink(  ) */
+static SQRESULT sq_glue_AddLink(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushinteger(v, self->AddLink());
+	return 1;
+}
+
+/* void AddPage( FPDF::e_orientation orientation  = FPDF::e_orientation_none , FPDF::st_pagesize * psize  = 0 ) */
+static SQRESULT sq_glue_AddPage(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_INTEGER(v, 2, orientation, FPDF::e_orientation_none);
+	SQ_OPT_STRING(v, 3, psize, 0);
+	self->AddPage((FPDF::e_orientation)orientation, 0);
+	return 0;
+}
+
+/* void AliasNbPages( char const * alias  = "{nb}" ) */
+static SQRESULT sq_glue_AliasNbPages(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_STRING(v, 2, alias, "{nb}");
+	self->AliasNbPages(alias);
+	return 0;
+}
+
+/* int CalcLines( pdf_float_t w , char const * txt ) */
+static SQRESULT sq_glue_CalcLines(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_GET_STRING(v, 3, txt);
+	sq_pushinteger(v, self->CalcLines(w, txt));
+	return 1;
+}
+
+/* void Cell( pdf_float_t w , pdf_float_t h  = 0.0f , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_Cell(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0.0f);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->Cell(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void CellFit( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 , bool scale  = false , bool force  = true ) */
+static SQRESULT sq_glue_CellFit(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	SQ_OPT_INTEGER(v, 10, scale, false);
+	SQ_OPT_INTEGER(v, 11, force, true);
+	self->CellFit(w, h, txt, border, ln, align, fill, link, scale, force);
+	return 0;
+}
+
+/* void CellFitScale( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_CellFitScale(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->CellFitScale(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void CellFitScaleForce( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_CellFitScaleForce(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->CellFitScaleForce(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void CellFitSpace( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_CellFitSpace(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->CellFitSpace(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void CellFitSpaceForce( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_CellFitSpaceForce(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->CellFitSpaceForce(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void CheckPageBreak( pdf_float_t height ) */
+static SQRESULT sq_glue_CheckPageBreak(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, height);
+	self->CheckPageBreak(height);
+	return 0;
+}
+
+/* void Circle( pdf_float_t x , pdf_float_t y , pdf_float_t r , char const * style  = "D" ) */
+static SQRESULT sq_glue_Circle(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, r);
+	SQ_OPT_STRING(v, 5, style, "D");
+	self->Circle(x, y, r, style);
+	return 0;
+}
+
+/* void ClippedCell( pdf_float_t w , pdf_float_t h  = 0 , char const * txt  = 0 , char const * border  = 0 , int ln  = 0 , char align  = ' ' , bool fill  = false , int link  = 0 ) */
+static SQRESULT sq_glue_ClippedCell(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_OPT_FLOAT(v, 3, h, 0);
+	SQ_OPT_STRING(v, 4, txt, 0);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, ln, 0);
+	SQ_OPT_INTEGER(v, 7, align, ' ');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	SQ_OPT_INTEGER(v, 9, link, 0);
+	self->ClippedCell(w, h, txt, border, ln, align, fill, link);
+	return 0;
+}
+
+/* void ClippingRect( pdf_float_t x , pdf_float_t y , pdf_float_t w , pdf_float_t h , bool outline  = false ) */
+static SQRESULT sq_glue_ClippingRect(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, w);
+	SQ_GET_FLOAT(v, 5, h);
+	SQ_OPT_INTEGER(v, 6, outline, false);
+	self->ClippingRect(x, y, w, h, outline);
+	return 0;
+}
+
+/* void ClippingText( pdf_float_t x , pdf_float_t y , char const * txt , bool outline  = false ) */
+static SQRESULT sq_glue_ClippingText(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_STRING(v, 4, txt);
+	SQ_OPT_INTEGER(v, 5, outline, false);
+	self->ClippingText(x, y, txt, outline);
+	return 0;
+}
+
+/* void Close(  ) */
+static SQRESULT sq_glue_Close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	self->Close();
+	return 0;
+}
+
+/* void Ellipse( pdf_float_t x , pdf_float_t y , pdf_float_t rx , pdf_float_t ry , char const * style  = "D" ) */
+static SQRESULT sq_glue_Ellipse(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, rx);
+	SQ_GET_FLOAT(v, 5, ry);
+	SQ_OPT_STRING(v, 6, style, "D");
+	self->Ellipse(x, y, rx, ry, style);
+	return 0;
+}
+
+/* void Error( char const * msg ) */
+static SQRESULT sq_glue_Error(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, msg);
+	self->Error(msg);
+	return 0;
+}
+
+/* void Footer(  ) */
+static SQRESULT sq_glue_Footer(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	self->FPDF::Footer();
+	return 0;
+}
+
+/* const & GetAliasNbPages(  ) */
+static SQRESULT sq_glue_GetAliasNbPages(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	std::string str = self->GetAliasNbPages();
+	sq_pushstring(v, str.c_str(), str.size());
+	return 1;
+}
+
+/* void GetDrawColor( FPDF::pdf_color_t & color ) */
+static SQRESULT sq_glue_GetDrawColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, color);
+	//self->GetDrawColor(color);
+	return 0;
+}
+
+/* void GetFillColor( FPDF::pdf_color_t & color ) */
+static SQRESULT sq_glue_GetFillColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, color);
+	//self->GetFillColor(color);
+	return 0;
+}
+
+/* void GetFontSettings( font_settings_st & fs ) */
+static SQRESULT sq_glue_GetFontSettings(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, fs);
+	//self->GetFontSettings(fs);
+	return 0;
+}
+
+/* pdf_float_t GetFontSize(  ) */
+static SQRESULT sq_glue_GetFontSize(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetFontSize());
+	return 1;
+}
+
+/* pdf_float_t GetH(  ) */
+static SQRESULT sq_glue_GetH(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetH());
+	return 1;
+}
+
+/* pdf_float_t GetLeftMargin(  ) */
+static SQRESULT sq_glue_GetLeftMargin(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetLeftMargin());
+	return 1;
+}
+
+/* pdf_float_t GetRightMargin(  ) */
+static SQRESULT sq_glue_GetRightMargin(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetRightMargin());
+	return 1;
+}
+
+/* pdf_float_t GetStringWidth( char const * s ) */
+static SQRESULT sq_glue_GetStringWidth(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, s);
+	sq_pushfloat(v, self->GetStringWidth(s));
+	return 1;
+}
+
+/* void GetTextColor( FPDF::pdf_color_t & color ) */
+static SQRESULT sq_glue_GetTextColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, color);
+	//self->GetTextColor(color);
+	return 0;
+}
+
+/* pdf_float_t GetW(  ) */
+static SQRESULT sq_glue_GetW(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetW());
+	return 1;
+}
+
+/* pdf_float_t GetX(  ) */
+static SQRESULT sq_glue_GetX(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetX());
+	return 1;
+}
+
+/* pdf_float_t GetY(  ) */
+static SQRESULT sq_glue_GetY(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushfloat(v, self->GetY());
+	return 1;
+}
+
+/* void Header(  ) */
+static SQRESULT sq_glue_Header(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	self->FPDF::Header();
+	return 0;
+}
+
+/* void Image( char const * file , pdf_float_t x  = -1 , pdf_float_t y  = -1 , pdf_float_t w  = 0.0 , pdf_float_t h  = 0.0 , char const * atype  = 0 , int link  = 0 ) */
+static SQRESULT sq_glue_Image(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, file);
+	SQ_OPT_FLOAT(v, 3, x, -1);
+	SQ_OPT_FLOAT(v, 4, y, -1);
+	SQ_OPT_FLOAT(v, 5, w, 0.0);
+	SQ_OPT_FLOAT(v, 6, h, 0.0);
+	SQ_OPT_STRING(v, 7, atype, 0);
+	SQ_OPT_INTEGER(v, 8, link, 0);
+	self->Image(file, x, y, w, h, atype, link);
+	return 0;
+}
+
+/* void IncludeJS( char const * script ) */
+static SQRESULT sq_glue_IncludeJS(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, script);
+	self->IncludeJS(script);
+	return 0;
+}
+
+/* void Line( pdf_float_t x1 , pdf_float_t y1 , pdf_float_t x2 , pdf_float_t y2 ) */
+static SQRESULT sq_glue_Line(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x1);
+	SQ_GET_FLOAT(v, 3, y1);
+	SQ_GET_FLOAT(v, 4, x2);
+	SQ_GET_FLOAT(v, 5, y2);
+	self->Line(x1, y1, x2, y2);
+	return 0;
+}
+
+/* void Link( pdf_float_t x , pdf_float_t y , pdf_float_t w , pdf_float_t h , int link ) */
+static SQRESULT sq_glue_Link(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, w);
+	SQ_GET_FLOAT(v, 5, h);
+	SQ_GET_INTEGER(v, 6, link);
+	self->Link(x, y, w, h, link);
+	return 0;
+}
+
+/* void Ln( pdf_float_t h  = 0.0 ) */
+static SQRESULT sq_glue_Ln(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_FLOAT(v, 2, h, 0.0);
+	self->Ln(h);
+	return 0;
+}
+
+/* void MultiCell( pdf_float_t w , pdf_float_t h , char const * txt , char const * border  = 0 , char align  = 'J' , bool fill  = false ) */
+static SQRESULT sq_glue_MultiCell(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_GET_FLOAT(v, 3, h);
+	SQ_GET_STRING(v, 4, txt);
+	SQ_OPT_STRING(v, 5, border, 0);
+	SQ_OPT_INTEGER(v, 6, align, 'J');
+	SQ_OPT_INTEGER(v, 7, fill, false);
+	self->MultiCell(w, h, txt, border, align, fill);
+	return 0;
+}
+
+/* void MultiCellBlt( pdf_float_t w , pdf_float_t h , char const * blt , char const * txt , char const * border  = 0 , char align  = 'J' , bool fill  = false ) */
+static SQRESULT sq_glue_MultiCellBlt(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, w);
+	SQ_GET_FLOAT(v, 3, h);
+	SQ_GET_STRING(v, 4, blt);
+	SQ_GET_STRING(v, 5, txt);
+	SQ_OPT_STRING(v, 6, border, 0);
+	SQ_OPT_INTEGER(v, 7, align, 'J');
+	SQ_OPT_INTEGER(v, 8, fill, false);
+	self->MultiCellBlt(w, h, blt, txt, border, align, fill);
+	return 0;
+}
+
+/* void Open(  ) */
+static SQRESULT sq_glue_Open(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	self->Open();
+	return 0;
+}
+
+/* string Output( char const * name  = 0 , char dest  = ' ' ) */
+static SQRESULT sq_glue_Output(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_STRING(v, 2, name, 0);
+	SQ_OPT_INTEGER(v, 3, dest, ' ');
+	std::string str = self->Output(name, dest);
+	sq_pushstring(v, str.c_str(), str.size());
+	return 1;
+}
+
+/* int PageNo(  ) */
+static SQRESULT sq_glue_PageNo(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushinteger(v, self->PageNo());
+	return 1;
+}
+
+/* void Rect( pdf_float_t x , pdf_float_t y , pdf_float_t w , pdf_float_t h , char const * style  = 0 ) */
+static SQRESULT sq_glue_Rect(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, w);
+	SQ_GET_FLOAT(v, 5, h);
+	SQ_OPT_STRING(v, 6, style, 0);
+	self->Rect(x, y, w, h, style);
+	return 0;
+}
+
+/* void Rotate( pdf_float_t angle , pdf_float_t x  = -1 , pdf_float_t y  = -1 ) */
+static SQRESULT sq_glue_Rotate(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, angle);
+	SQ_OPT_FLOAT(v, 3, x, -1);
+	SQ_OPT_FLOAT(v, 4, y, -1);
+	self->Rotate(angle, x, y);
+	return 0;
+}
+
+/* void RotatedText( pdf_float_t x , pdf_float_t y , char const * txt , pdf_float_t angle ) */
+static SQRESULT sq_glue_RotatedText(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_STRING(v, 4, txt);
+	SQ_GET_FLOAT(v, 5, angle);
+	self->RotatedText(x, y, txt, angle);
+	return 0;
+}
+
+/* void RoundedRect( pdf_float_t x , pdf_float_t y , pdf_float_t w , pdf_float_t h , pdf_float_t r , char const * style  = "" ) */
+static SQRESULT sq_glue_RoundedRect(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_FLOAT(v, 4, w);
+	SQ_GET_FLOAT(v, 5, h);
+	SQ_GET_FLOAT(v, 6, r);
+	SQ_OPT_STRING(v, 7, style, "");
+	self->RoundedRect(x, y, w, h, r, style);
+	return 0;
+}
+
+/* void SetAlpha( pdf_float_t alpha , char const * bm  = 0 ) */
+static SQRESULT sq_glue_SetAlpha(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, alpha);
+	SQ_OPT_STRING(v, 3, bm, 0);
+	self->SetAlpha(alpha, bm);
+	return 0;
+}
+
+/* void SetAuthor( char const * author ) */
+static SQRESULT sq_glue_SetAuthor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, author);
+	self->SetAuthor(author);
+	return 0;
+}
+
+/* void SetAutoPageBreak( bool b , pdf_float_t margin  = 0.0f ) */
+static SQRESULT sq_glue_SetAutoPageBreak(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, b);
+	SQ_OPT_FLOAT(v, 3, margin, 0.0f);
+	self->SetAutoPageBreak(b, margin);
+	return 0;
+}
+
+/* void SetCompression( bool compress ) */
+static SQRESULT sq_glue_SetCompression(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_BOOL(v, 2, compress);
+	self->SetCompression(compress);
+	return 0;
+}
+
+/* void SetCreator( char const * creator ) */
+static SQRESULT sq_glue_SetCreator(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, creator);
+	self->SetCreator(creator);
+	return 0;
+}
+
+/* void SetDash( pdf_float_t black  = -1 , pdf_float_t white  = -1 ) */
+static SQRESULT sq_glue_SetDash(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_FLOAT(v, 2, black, -1);
+	SQ_OPT_FLOAT(v, 3, white, -1);
+	self->SetDash(black, white);
+	return 0;
+}
+
+/* void SetDisplayMode( FPDF::e_zoom_mode zoom , FPDF::e_layout_mode layout  = FPDF::e_layout_default ) */
+static SQRESULT sq_glue_SetDisplayMode(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, zoom);
+	SQ_OPT_INTEGER(v, 3, layout, FPDF::e_layout_default);
+	//self->SetDisplayMode(zoom, layout);
+	return 0;
+}
+
+/* void SetDoubleSided( pdf_float_t inner  = 7 , pdf_float_t outer  = 13 ) */
+static SQRESULT sq_glue_SetDoubleSided(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_FLOAT(v, 2, inner, 7);
+	SQ_OPT_FLOAT(v, 3, outer, 13);
+	self->SetDoubleSided(inner, outer);
+	return 0;
+}
+
+/* void SetDrawColor( unsigned char r , unsigned char g , unsigned char b ) */
+static SQRESULT sq_glue_SetDrawColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, r);
+	SQ_GET_INTEGER(v, 3, g);
+	SQ_GET_INTEGER(v, 4, b);
+	self->SetDrawColor(r, g, b);
+	return 0;
+}
+
+/* void SetFillColor( unsigned char r , unsigned char g , unsigned char b ) */
+static SQRESULT sq_glue_SetFillColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, r);
+	SQ_GET_INTEGER(v, 3, g);
+	SQ_GET_INTEGER(v, 4, b);
+	self->SetFillColor(r, g, b);
+	return 0;
+}
+
+/* void SetFont( char const * afamily  = 0 , char const * astyle  = 0 , pdf_float_t size  = 0 ) */
+static SQRESULT sq_glue_SetFont(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_STRING(v, 2, afamily, 0);
+	SQ_OPT_STRING(v, 3, astyle, 0);
+	SQ_OPT_FLOAT(v, 4, size, 0);
+	self->SetFont(afamily, astyle, size);
+	return 0;
+}
+
+/* void SetFontSettings( font_settings_st & fs ) */
+static SQRESULT sq_glue_SetFontSettings(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, fs);
+	//self->SetFontSettings(fs);
+	return 0;
+}
+
+/* void SetFontSize( pdf_float_t size ) */
+static SQRESULT sq_glue_SetFontSize(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, size);
+	self->SetFontSize(size);
+	return 0;
+}
+
+/* void SetKeywords( char const * keywords ) */
+static SQRESULT sq_glue_SetKeywords(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, keywords);
+	self->SetKeywords(keywords);
+	return 0;
+}
+
+/* void SetLeftMargin( pdf_float_t margin ) */
+static SQRESULT sq_glue_SetLeftMargin(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, margin);
+	self->SetLeftMargin(margin);
+	return 0;
+}
+
+/* void SetLineWidth( pdf_float_t width ) */
+static SQRESULT sq_glue_SetLineWidth(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, width);
+	self->SetLineWidth(width);
+	return 0;
+}
+
+/* void SetLink( int link , pdf_float_t y  = 0 , int page  = -1 ) */
+static SQRESULT sq_glue_SetLink(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, link);
+	SQ_OPT_FLOAT(v, 3, y, 0);
+	SQ_OPT_INTEGER(v, 4, page, -1);
+	self->SetLink(link, y, page);
+	return 0;
+}
+
+/* void SetMargins( pdf_float_t left , pdf_float_t top , pdf_float_t right  = 0.0f ) */
+static SQRESULT sq_glue_SetMargins(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, left);
+	SQ_GET_FLOAT(v, 3, top);
+	SQ_OPT_FLOAT(v, 4, right, 0.0f);
+	self->SetMargins(left, top, right);
+	return 0;
+}
+
+/* void SetRightMargin( pdf_float_t margin ) */
+static SQRESULT sq_glue_SetRightMargin(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, margin);
+	self->SetRightMargin(margin);
+	return 0;
+}
+
+/* void SetSubject( char const * subject ) */
+static SQRESULT sq_glue_SetSubject(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, subject);
+	self->SetSubject(subject);
+	return 0;
+}
+
+/* void SetTextColor( unsigned char r , unsigned char g , unsigned char b ) */
+static SQRESULT sq_glue_SetTextColor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, r);
+	SQ_GET_INTEGER(v, 3, g);
+	SQ_GET_INTEGER(v, 4, b);
+	self->SetTextColor(r, g, b);
+	return 0;
+}
+
+/* void SetTitle( char const * title ) */
+static SQRESULT sq_glue_SetTitle(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_STRING(v, 2, title);
+	self->SetTitle(title);
+	return 0;
+}
+
+/* void SetTopMargin( pdf_float_t margin ) */
+static SQRESULT sq_glue_SetTopMargin(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, margin);
+	self->SetTopMargin(margin);
+	return 0;
+}
+
+/* void SetX( pdf_float_t x ) */
+static SQRESULT sq_glue_SetX(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	self->SetX(x);
+	return 0;
+}
+
+/* void SetXY( pdf_float_t x , pdf_float_t y ) */
+static SQRESULT sq_glue_SetXY(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	self->SetXY(x, y);
+	return 0;
+}
+
+/* void SetY( pdf_float_t y ) */
+static SQRESULT sq_glue_SetY(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, y);
+	self->SetY(y);
+	return 0;
+}
+
+/* void Text( pdf_float_t x , pdf_float_t y , char const * txt ) */
+static SQRESULT sq_glue_Text(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_STRING(v, 4, txt);
+	self->Text(x, y, txt);
+	return 0;
+}
+
+/* void TextShadow( pdf_float_t x , pdf_float_t y , char const * txt , pdf_float_t displacement  = .3 ) */
+static SQRESULT sq_glue_TextShadow(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, x);
+	SQ_GET_FLOAT(v, 3, y);
+	SQ_GET_STRING(v, 4, txt);
+	SQ_OPT_FLOAT(v, 5, displacement, .3);
+	self->TextShadow(x, y, txt, displacement);
+	return 0;
+}
+
+/* void UnsetClipping(  ) */
+static SQRESULT sq_glue_UnsetClipping(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	self->UnsetClipping();
+	return 0;
+}
+
+/* void Write( pdf_float_t h , char const * txt , int link  = 0 ) */
+static SQRESULT sq_glue_Write(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_GET_FLOAT(v, 2, h);
+	SQ_GET_STRING(v, 3, txt);
+	SQ_OPT_INTEGER(v, 4, link, 0);
+	self->Write(h, txt, link);
+	return 0;
+}
+
+/* int getCustomZoom(  ) */
+static SQRESULT sq_glue_getCustomZoom(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	sq_pushinteger(v, self->getCustomZoom());
+	return 1;
+}
+
+/* void reset( FPDF::e_orientation orientation  = FPDF::e_orientation_portrait , FPDF::e_units unit  = FPDF::e_mm , FPDF::e_page_sizes psize  = FPDF::e_A4 ) */
+static SQRESULT sq_glue_reset(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_SQ_FPDF();
+	SQ_OPT_INTEGER(v, 2, orientation, FPDF::e_orientation_portrait);
+	SQ_OPT_INTEGER(v, 3, unit, FPDF::e_mm);
+	SQ_OPT_INTEGER(v, 4, psize, FPDF::e_A4);
+	//self->reset(orientation, unit, psize);
+	return 0;
+}
+
+/* void setCustomZoom( int zoom ) */
+static SQRESULT sq_glue_setCustomZoom(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_SQ_FPDF();
+	SQ_GET_INTEGER(v, 2, zoom);
+	self->setCustomZoom(zoom);
+	return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_glue_##name,nparams,tycheck}
+static SQRegFunction sq_glue_my_methods[] =
+{
+	_DECL_FUNC(constructor,  1, _SC("x")),
+	_DECL_FUNC(AcceptPageBreak,  1, _SC("x")),
+	_DECL_FUNC(AddFont,  -2, _SC("xsss")),
+	_DECL_FUNC(AddLink,  1, _SC("x")),
+	_DECL_FUNC(AddPage,  -1, _SC("xis")),
+	_DECL_FUNC(AliasNbPages,  -1, _SC("xs")),
+	_DECL_FUNC(CalcLines,  3, _SC("xns")),
+	_DECL_FUNC(Cell,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(CellFit,  -2, _SC("xnnssiiiiii")),
+	_DECL_FUNC(CellFitScale,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(CellFitScaleForce,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(CellFitSpace,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(CellFitSpaceForce,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(CheckPageBreak,  2, _SC("xn")),
+	_DECL_FUNC(Circle,  -4, _SC("xnnns")),
+	_DECL_FUNC(ClippedCell,  -2, _SC("xnnssiiii")),
+	_DECL_FUNC(ClippingRect,  -5, _SC("xnnnni")),
+	_DECL_FUNC(ClippingText,  -4, _SC("xnnsi")),
+	_DECL_FUNC(Close,  1, _SC("x")),
+	_DECL_FUNC(Ellipse,  -5, _SC("xnnnns")),
+	_DECL_FUNC(Error,  2, _SC("xs")),
+	_DECL_FUNC(Footer,  1, _SC("x")),
+	_DECL_FUNC(GetAliasNbPages,  1, _SC("x")),
+	_DECL_FUNC(GetDrawColor,  2, _SC("xi")),
+	_DECL_FUNC(GetFillColor,  2, _SC("xi")),
+	_DECL_FUNC(GetFontSettings,  2, _SC("xi")),
+	_DECL_FUNC(GetFontSize,  1, _SC("x")),
+	_DECL_FUNC(GetH,  1, _SC("x")),
+	_DECL_FUNC(GetLeftMargin,  1, _SC("x")),
+	_DECL_FUNC(GetRightMargin,  1, _SC("x")),
+	_DECL_FUNC(GetStringWidth,  2, _SC("xs")),
+	_DECL_FUNC(GetStringWidth,  2, _SC("xi")),
+	_DECL_FUNC(GetTextColor,  2, _SC("xi")),
+	_DECL_FUNC(GetW,  1, _SC("x")),
+	_DECL_FUNC(GetX,  1, _SC("x")),
+	_DECL_FUNC(GetY,  1, _SC("x")),
+	_DECL_FUNC(Header,  1, _SC("x")),
+	_DECL_FUNC(Image,  -2, _SC("xsnnnnsi")),
+	_DECL_FUNC(IncludeJS,  2, _SC("xs")),
+	_DECL_FUNC(Line,  5, _SC("xnnnn")),
+	_DECL_FUNC(Link,  6, _SC("xnnnni")),
+	_DECL_FUNC(Ln,  -1, _SC("xn")),
+	_DECL_FUNC(MultiCell,  -4, _SC("xnnssii")),
+	_DECL_FUNC(MultiCellBlt,  -5, _SC("xnnsssii")),
+	_DECL_FUNC(Open,  1, _SC("x")),
+	_DECL_FUNC(Output,  -1, _SC("xsi")),
+	_DECL_FUNC(PageNo,  1, _SC("x")),
+	_DECL_FUNC(Rect,  -5, _SC("xnnnns")),
+	_DECL_FUNC(Rotate,  -2, _SC("xnnn")),
+	_DECL_FUNC(RotatedText,  5, _SC("xnnsn")),
+	_DECL_FUNC(RoundedRect,  -6, _SC("xnnnnns")),
+	_DECL_FUNC(SetAlpha,  -2, _SC("xns")),
+	_DECL_FUNC(SetAuthor,  2, _SC("xs")),
+	_DECL_FUNC(SetAutoPageBreak,  -2, _SC("xin")),
+	_DECL_FUNC(SetCompression,  2, _SC("xb")),
+	_DECL_FUNC(SetCreator,  2, _SC("xs")),
+	_DECL_FUNC(SetDash,  -1, _SC("xnn")),
+	_DECL_FUNC(SetDisplayMode,  -2, _SC("xii")),
+	_DECL_FUNC(SetDoubleSided,  -1, _SC("xnn")),
+	_DECL_FUNC(SetDrawColor,  -2, _SC("xiii")),
+	_DECL_FUNC(SetFillColor,  -2, _SC("xiii")),
+	_DECL_FUNC(SetFont,  -1, _SC("xssn")),
+	_DECL_FUNC(SetFontSettings,  2, _SC("xi")),
+	_DECL_FUNC(SetFontSize,  2, _SC("xn")),
+	_DECL_FUNC(SetKeywords,  2, _SC("xs")),
+	_DECL_FUNC(SetLeftMargin,  2, _SC("xn")),
+	_DECL_FUNC(SetLineWidth,  2, _SC("xn")),
+	_DECL_FUNC(SetLink,  -2, _SC("xini")),
+	_DECL_FUNC(SetMargins,  -3, _SC("xnnn")),
+	_DECL_FUNC(SetRightMargin,  2, _SC("xn")),
+	_DECL_FUNC(SetSubject,  2, _SC("xs")),
+	_DECL_FUNC(SetTextColor,  -2, _SC("xiii")),
+	_DECL_FUNC(SetTitle,  2, _SC("xs")),
+	_DECL_FUNC(SetTopMargin,  2, _SC("xn")),
+	_DECL_FUNC(SetX,  2, _SC("xn")),
+	_DECL_FUNC(SetXY,  3, _SC("xnn")),
+	_DECL_FUNC(SetY,  2, _SC("xn")),
+	_DECL_FUNC(Text,  4, _SC("xnns")),
+	_DECL_FUNC(TextShadow,  -4, _SC("xnnsn")),
+	_DECL_FUNC(UnsetClipping,  1, _SC("x")),
+	_DECL_FUNC(Write,  -3, _SC("xnsi")),
+	_DECL_FUNC(getCustomZoom,  1, _SC("x")),
+	_DECL_FUNC(reset,  -1, _SC("xiii")),
+	_DECL_FUNC(setCustomZoom,  2, _SC("xi")),
+	{0,0}
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_Sq_Fpdf(HSQUIRRELVM v)
+    {
+        sq_pushstring(v,SQ_FPDF_TAG,-1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(void*)SQ_FPDF_TAG);
+        sq_insert_reg_funcs(v, sq_glue_my_methods);
+        sq_newslot(v,-3,SQTrue);
+        return 1;
+    }
+
+#ifdef __cplusplus
+}
+#endif

+ 848 - 0
ext/sq_fs.c

@@ -0,0 +1,848 @@
+/*
+** LuaFileSystem
+** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem)
+**
+** File system manipulation library.
+** This library offers these functions:
+**   lfs.attributes (filepath [, attributename])
+**   lfs.chdir (path)
+**   lfs.currentdir ()
+**   lfs.dir (path)
+**   lfs.lock (fh, mode)
+**   lfs.lock_dir (path)
+**   lfs.mkdir (path)
+**   lfs.rmdir (path)
+**   lfs.setmode (filepath, mode)
+**   lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts
+**   lfs.touch (filepath [, atime [, mtime]])
+**   lfs.unlock (fh)
+**
+** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
+*
+* Ported to Squirrel by Domingo Alvarez Duarte
+*/
+
+#ifndef _WIN32
+#ifndef _AIX
+#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */
+#else
+#define _LARGE_FILES 1 /* AIX */
+#endif
+#endif
+
+#define _LARGEFILE64_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#include <io.h>
+#include <sys/locking.h>
+#ifdef __BORLANDC__
+ #include <utime.h>
+#else
+ #include <sys/utime.h>
+#endif
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <utime.h>
+#endif
+
+#include "squirrel.h"
+SQ_OPT_STRING_STRLEN();
+#include "sqfs.h"
+
+/* Define 'strerror' for systems that do not implement it */
+#ifdef NO_STRERROR
+#define strerror(_)	"System unable to describe the error"
+#endif
+
+/* Define 'getcwd' for systems that do not implement it */
+#ifdef NO_GETCWD
+#define getcwd(p,s)	NULL
+#define getcwd_error	"Function 'getcwd' not provided by system"
+#else
+#define getcwd_error    strerror(errno)
+  #ifdef _WIN32
+	 /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
+    #define LFS_MAXPATHLEN MAX_PATH
+  #else
+	/* For MAXPATHLEN: */
+    #include <sys/param.h>
+    #define LFS_MAXPATHLEN MAXPATHLEN
+  #endif
+#endif
+
+#define DIR_METATABLE "directory metatable"
+typedef struct dir_data {
+        int  closed;
+#ifdef _WIN32
+        long hFile;
+        char pattern[MAX_PATH+1];
+#else
+        DIR *dir;
+#endif
+} dir_data;
+
+#define LOCK_METATABLE "lock metatable"
+
+#ifdef _WIN32
+ #ifdef __BORLANDC__
+  #define lfs_setmode(L,file,m)   ((void)L, setmode(_fileno(file), m))
+  #define STAT_STRUCT struct stati64
+ #else
+  #define lfs_setmode(L,file,m)   ((void)L, _setmode(_fileno(file), m))
+  #define STAT_STRUCT struct _stati64
+ #endif
+#define STAT_FUNC _stati64
+#define LSTAT_FUNC STAT_FUNC
+#else
+#define _O_TEXT               0
+#define _O_BINARY             0
+#define lfs_setmode(L,file,m)   ((void)L, (void)file, (void)m, 0)
+#define STAT_STRUCT struct stat
+#define STAT_FUNC stat
+#define LSTAT_FUNC lstat
+#endif
+
+static const SQChar currFileName_key[] = _SC("currFileName");
+
+/*
+** This function changes the working (current) directory
+*/
+static int sqfs_chdir (HSQUIRRELVM v) {
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+	if (chdir(path)) {
+	    return sq_throwerror(v, "Unable to change working directory to '%s'\n%s\n",
+				path, chdir_error);
+	} else {
+		sq_pushbool (v, SQTrue);
+		return 1;
+	}
+}
+
+/*
+** This function returns the current directory
+** If unable to get the current directory, it returns nil
+**  and a string describing the error
+*/
+static int sqfs_currentdir (HSQUIRRELVM v) {
+  SQChar *path;
+  /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
+  char buf[LFS_MAXPATHLEN];
+  if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) {
+    return sq_throwerror(v, getcwd_error);
+  }
+  else {
+    sq_pushstring(v, buf, -1);
+    return 1;
+  }
+}
+#if 0
+/*
+** Check if the given element on the stack is a file and returns it.
+*/
+static FILE *check_file (HSQUIRRELVM v, int idx, const SQChar *funcname) {
+	FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*");
+	if (fh == NULL) {
+		return sq_throwerror(v, "%s: not a file", funcname);
+	} else if (*fh == NULL) {
+		return sq_throwerror(v, "%s: closed file", funcname);
+		return 0;
+	} else
+		return *fh;
+}
+
+
+/*
+**
+*/
+static int _file_lock (HSQUIRRELVM v, FILE *fh, const char *mode, const long start, long len, const char *funcname) {
+	int code;
+#ifdef _WIN32
+	/* lkmode valid values are:
+	   LK_LOCK    Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.
+	   LK_NBLCK   Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.
+	   LK_NBRLCK  Same as _LK_NBLCK.
+	   LK_RLCK    Same as _LK_LOCK.
+	   LK_UNLCK   Unlocks the specified bytes, which must have been previously locked.
+
+	   Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.
+
+	   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
+	*/
+	int lkmode;
+	switch (*mode) {
+		case 'r': lkmode = LK_NBLCK; break;
+		case 'w': lkmode = LK_NBLCK; break;
+		case 'u': lkmode = LK_UNLCK; break;
+		default : return sq_throwerror (v, "%s: invalid mode", funcname);
+	}
+	if (!len) {
+		fseek (fh, 0L, SEEK_END);
+		len = ftell (fh);
+	}
+	fseek (fh, start, SEEK_SET);
+	code = _locking (fileno(fh), lkmode, len);
+#else
+	struct flock f;
+	switch (*mode) {
+		case 'w': f.l_type = F_WRLCK; break;
+		case 'r': f.l_type = F_RDLCK; break;
+		case 'u': f.l_type = F_UNLCK; break;
+		default : return sq_throwerror(v, "%s: invalid mode", funcname);
+	}
+	f.l_whence = SEEK_SET;
+	f.l_start = (off_t)start;
+	f.l_len = (off_t)len;
+	code = fcntl (fileno(fh), F_SETLK, &f);
+#endif
+	return (code != -1);
+}
+
+#ifdef _WIN32
+typedef struct sqfs_Lock {
+  HANDLE fd;
+} lfs_Lock;
+static int sqfs_lock_dir(HSQUIRRELVM v) {
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+  HANDLE fd;
+  lfs_Lock *lock;
+  char *ln;
+  const char *lockfile = "/lockfile.sqfs";
+  ln = (char*)sq_malloc(path_size + strlen(lockfile) + 1);
+  if(!ln) return sq_throwerror(v, strerror(errno));
+
+  strcpy(ln, path); strcat(ln, lockfile);
+  if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) {
+        int en = GetLastError();
+        free(ln);
+        if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
+                sq_pushliteral(v, "File exists");
+        else
+                sq_pushstring(v, strerror(en), -1);
+        return 1;
+  }
+  free(ln);
+  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock));
+  lock->fd = fd;
+  luaL_getmetatable (L, LOCK_METATABLE);
+  lua_setmetatable (L, -2);
+  return 1;
+}
+static int sqfs_unlock_dir(HSQUIRRELVM v) {
+  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
+  CloseHandle(lock->fd);
+  return 0;
+}
+#else
+typedef struct sqfs_Lock {
+  char *ln;
+} lfs_Lock;
+static int sqfs_lock_dir(HSQUIRRELVM v) {
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+  lfs_Lock *lock;
+  char *ln;
+  const char *lockfile = "/lockfile.sqfs";
+  lock = (lfs_Lock*)lua_newuserdata(L, sizeof(sqfs_Lock));
+  ln = (char*)sq_malloc(path_size + strlen(lockfile) + 1);
+  if(!ln) return sq_throwerror(v, strerror(errno));
+  strcpy(ln, path); strcat(ln, lockfile);
+  if(symlink("lock", ln) == -1) {
+    free(ln);
+    return sq_throwerror(v, strerror(errno));
+  }
+  lock->ln = ln;
+  luaL_getmetatable (L, LOCK_METATABLE);
+  lua_setmetatable (L, -2);
+  return 1;
+}
+static int lfs_unlock_dir(HSQUIRRELVM v) {
+  lfs_Lock *lock = luaL_checkudata(L, 1, LOCK_METATABLE);
+  if(lock->ln) {
+    unlink(lock->ln);
+    free(lock->ln);
+    lock->ln = NULL;
+  }
+  return 0;
+}
+#endif
+
+#ifdef _WIN32
+static int lfs_g_setmode (HSQUIRRELVM v, FILE *f, int arg) {
+  static const int mode[] = {_O_TEXT, _O_BINARY};
+  static const char *const modenames[] = {"text", "binary", NULL};
+  int op = luaL_checkoption(L, arg, NULL, modenames);
+  int res = lfs_setmode(L, f, mode[op]);
+  if (res != -1) {
+    int i;
+    lua_pushboolean(L, 1);
+    for (i = 0; modenames[i] != NULL; i++) {
+      if (mode[i] == res) {
+        lua_pushstring(L, modenames[i]);
+        goto exit;
+      }
+    }
+    lua_pushnil(L);
+  exit:
+    return 2;
+  } else {
+    int en = errno;
+    lua_pushnil(L);
+    lua_pushfstring(L, "%s", strerror(en));
+    lua_pushinteger(L, en);
+    return 3;
+  }
+}
+#else
+static int lfs_g_setmode (HSQUIRRELVM v, FILE *f, int arg) {
+  return sq_throwerror(v, "setmode not supported on this platform");
+}
+#endif
+
+static int sqfs_setmode(HSQUIRRELVM v) {
+  return lfs_g_setmode(v, check_file(v, 1, "setmode"), 2);
+}
+
+/*
+** Locks a file.
+** @param #1 File handle.
+** @param #2 String with lock mode ('w'rite, 'r'ead).
+** @param #3 Number with start position (optional).
+** @param #4 Number with length (optional).
+*/
+static int sqfs_lock (HSQUIRRELVM v) {
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 3, mode);
+    SQ_OPT_INTEGER(v, 4, start, 0);
+    SQ_OPT_INTEGER(v, 5, len, 0);
+	FILE *fh = check_file (L, 1, SC("lock");
+	if (_file_lock (v, fh, mode, start, len, _SC("lock")) {
+		sq_pushbool (v, SQTrue);
+		return 1;
+	} else {
+		return sq_throwerror(v, "%s", strerror(errno));
+	}
+}
+
+
+/*
+** Unlocks a file.
+** @param #1 File handle.
+** @param #2 Number with start position (optional).
+** @param #3 Number with length (optional).
+*/
+static int sqfs_unlock (HSQUIRRELVM v) {
+    SQ_FUNC_VARS(v);
+    SQ_OPT_INTEGER(v, 3, start, 0);
+    SQ_OPT_INTEGER(v, 4, len, 0);
+	FILE *fh = check_file (L, 1, "unlock");
+	if (_file_lock (v, fh, "u", start, len, "unlock")) {
+		sq_pushbool (v, SQTrue);
+		return 1;
+	} else {
+		return sq_throwerror (v, "%s", strerror(errno));
+	}
+}
+#endif
+
+/*
+** Creates a link.
+** @param #1 Object to link to.
+** @param #2 Name of link.
+** @param #3 True if link is symbolic (optional).
+*/
+static int sqfs_link(HSQUIRRELVM v)
+{
+#ifndef _WIN32
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 2, oldpath);
+    SQ_GET_STRING(v, 3, newpath);
+    SQ_OPT_BOOL(v, 4, bsym, SQFalse);
+    sq_pushinteger(v, (bsym ? symlink : link)(oldpath, newpath));
+    return 1;
+#else
+    return sq_throwerror(v, "make_link is not supported on Windows");
+#endif
+}
+
+static int sqfs_mkdir (HSQUIRRELVM v) {
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+	int fail;
+#ifdef _WIN32
+	int oldmask = umask (0);
+	fail = _mkdir (path);
+#else
+	mode_t oldmask = umask( (mode_t)0 );
+	fail =  mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
+	                     S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH );
+#endif
+	if (fail) {
+        return sq_throwerror (v, "%s", strerror(errno));
+	}
+	umask (oldmask);
+	sq_pushbool (v, SQTrue);
+	return 1;
+}
+
+/*
+** Removes a directory.
+** @param #1 Directory path.
+*/
+static int sqfs_rmdir (HSQUIRRELVM v) {
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+	int fail;
+
+	fail = rmdir (path);
+
+	if (fail) {
+		return sq_throwerror (v, "%s", strerror(errno));
+	}
+	sq_pushbool (v, SQTrue);
+	return 1;
+}
+
+static const SQChar SQFS_DIR_TAG[] = _SC("sqfs_dir_tag");
+#define GET_dir_INSTANCE() SQ_GET_INSTANCE(v, 1, dir_data, SQFS_DIR_TAG)
+
+static void _dir_close_dir(dir_data *dir)
+{
+#ifdef _WIN32
+    if (!dir->closed && dir->hFile) {
+            _findclose (dir->hFile);
+    }
+#else
+    if (!dir->closed && dir->dir) {
+            closedir (dir->dir);
+    }
+#endif
+    dir->closed = 1;
+}
+
+static SQRESULT _dir_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	dir_data *dir = ((dir_data *)p);
+	_dir_close_dir(dir);
+	sq_free(dir, sizeof(dir_data));
+	return 0;
+}
+
+static SQRESULT _dir_constructor(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, path);
+	dir_data *dir = (dir_data*)sq_malloc(sizeof(dir_data));
+	dir->closed = 0;
+#ifdef _WIN32
+    dir->hFile = 0L;
+    if (strlen(path) > MAX_PATH-2)
+      return sq_throwerror(v, "path too long: %s", path);
+    else
+      scsnprintf (dir->pattern, sizeof(dir->pattern), "%s/*", path);
+#else
+    dir->dir = opendir (path);
+    if (dir->dir == NULL)
+      return sq_throwerror(v, "cannot open %s: %s", path, strerror (errno));
+#endif
+    //sq_pushstring(v, currFileName_key, sizeof(currFileName_key)-1); //store file name between iterations
+    //sq_pushliteral(v, _SC(""));
+    //if(sq_set(v, 1) != SQ_OK) return SQ_ERROR;
+
+    sq_setinstanceup(v, 1, dir); //replace self for this instance with this new sqlite3_stmt
+    sq_setreleasehook(v,1, _dir_releasehook);
+	return 1;
+}
+
+static SQRESULT _dir_close(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_dir_INSTANCE();
+    _dir_close_dir(self);
+    return 0;
+}
+
+static SQRESULT _dir__get(HSQUIRRELVM v)
+{
+    sq_pushstring(v, currFileName_key, sizeof(currFileName_key)-1);
+    if(sq_get(v, 1) == SQ_ERROR) sq_pushnull(v);
+    return 1;
+}
+
+static SQRESULT _dir__nexti(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_dir_INSTANCE();
+	SQInteger idx;
+	if(sq_gettype(v,2) == OT_NULL) idx = 0;
+	else
+	{
+        if(!SQ_SUCCEEDED(sq_getinteger(v, 2, &idx)))
+            return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
+        ++idx;
+	}
+#ifdef _WIN32
+    struct _finddata_t c_file;
+#else
+    struct dirent *entry;
+#endif
+    const char *fname;
+    if(self->closed) return sq_throwerror(v, "closed directory");
+#ifdef _WIN32
+    if (self->hFile == 0L) { /* first entry */
+        if ((self->hFile = _findfirst (self->pattern, &c_file)) == -1L) {
+                self->closed = 1;
+                return sq_throwerror(v, strerror (errno));
+        }
+    } else { /* next entry */
+        if (_findnext (self->hFile, &c_file) == -1L) {
+                /* no more entries => close directory */
+                _findclose (self->hFile);
+                self->closed = 1;
+                sq_pushnull(v);
+                return 1;
+        }
+    }
+    fname = c_file.name;
+#else
+    if ((entry = readdir (self->dir)) == NULL) {
+        /* no more entries => close directory */
+        closedir (self->dir);
+        self->closed = 1;
+        sq_pushnull(v);
+        return 1;
+    }
+    fname = entry->d_name;
+#endif
+    sq_pushstring(v, currFileName_key, sizeof(currFileName_key)-1);
+    sq_pushstring(v, fname, -1);
+    if(sq_set(v, 1) != SQ_OK) return SQ_ERROR;
+
+	sq_pushinteger(v, idx);
+	return 1;
+}
+
+#define _DECL_DIR_FUNC(name,nparams,typecheck) {_SC(#name),_dir_##name,nparams,typecheck}
+static SQRegFunction _dir_methods[] = {
+	_DECL_DIR_FUNC(constructor,-1,_SC("xs")),
+	_DECL_DIR_FUNC(close,1,_SC("x")),
+	_DECL_DIR_FUNC(_nexti,2,_SC("x.")),
+	_DECL_DIR_FUNC(_get,2,_SC("xn")),
+	{0,0,0,0}
+};
+
+
+#ifdef _WIN32
+ #ifndef S_ISDIR
+   #define S_ISDIR(mode)  (mode&_S_IFDIR)
+ #endif
+ #ifndef S_ISREG
+   #define S_ISREG(mode)  (mode&_S_IFREG)
+ #endif
+ #ifndef S_ISLNK
+   #define S_ISLNK(mode)  (0)
+ #endif
+ #ifndef S_ISSOCK
+   #define S_ISSOCK(mode)  (0)
+ #endif
+ #ifndef S_ISFIFO
+   #define S_ISFIFO(mode)  (0)
+ #endif
+ #ifndef S_ISCHR
+   #define S_ISCHR(mode)  (mode&_S_IFCHR)
+ #endif
+ #ifndef S_ISBLK
+   #define S_ISBLK(mode)  (0)
+ #endif
+#endif
+/*
+** Convert the inode protection mode to a string.
+*/
+#ifdef _WIN32
+static const SQChar *mode2string (unsigned short mode) {
+#else
+static const SQChar *mode2string (mode_t mode) {
+#endif
+  if ( S_ISREG(mode) )
+    return _SC("file");
+  else if ( S_ISDIR(mode) )
+    return _SC("directory");
+  else if ( S_ISLNK(mode) )
+	return _SC("link");
+  else if ( S_ISSOCK(mode) )
+    return _SC("socket");
+  else if ( S_ISFIFO(mode) )
+	return _SC("named pipe");
+  else if ( S_ISCHR(mode) )
+	return _SC("char device");
+  else if ( S_ISBLK(mode) )
+	return _SC("block device");
+  else
+	return _SC("other");
+}
+
+
+/*
+** Set access time and modification values for file
+*/
+static int sqfs_touch (HSQUIRRELVM v) {
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 2, file);
+	struct utimbuf utb, *buf;
+
+	if (_top_ == 2) /* set to current date/time */
+		buf = NULL;
+	else {
+	    SQ_OPT_INTEGER(v, 3, actime, 0);
+	    SQ_OPT_INTEGER(v, 4, modtime, actime);
+		utb.actime = (time_t)actime;
+		utb.modtime = (time_t)modtime;
+		buf = &utb;
+	}
+	if (utime (file, buf)) {
+		return sq_throwerror(v, "%s", strerror (errno));
+	}
+	sq_pushbool (v, SQTrue);
+	return 1;
+}
+
+
+/* inode protection mode */
+static void push_st_mode (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushstring (v, mode2string (info->st_mode), -1);
+}
+/* device inode resides on */
+static void push_st_dev (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_dev);
+}
+/* inode's number */
+static void push_st_ino (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_ino);
+}
+/* number of hard links to the file */
+static void push_st_nlink (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_nlink);
+}
+/* user-id of owner */
+static void push_st_uid (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_uid);
+}
+/* group-id of owner */
+static void push_st_gid (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_gid);
+}
+/* device type, for special file inode */
+static void push_st_rdev (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_rdev);
+}
+/* time of last access */
+static void push_st_atime (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, info->st_atime);
+}
+/* time of last data modification */
+static void push_st_mtime (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, info->st_mtime);
+}
+/* time of last file status change */
+static void push_st_ctime (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, info->st_ctime);
+}
+/* file size, in bytes */
+static void push_st_size (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_size);
+}
+#ifndef _WIN32
+/* blocks allocated for file */
+static void push_st_blocks (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_blocks);
+}
+/* optimal file system I/O blocksize */
+static void push_st_blksize (HSQUIRRELVM v, STAT_STRUCT *info) {
+	sq_pushinteger (v, (SQInteger)info->st_blksize);
+}
+#endif
+static void push_invalid (HSQUIRRELVM v, STAT_STRUCT *info) {
+  sq_throwerror(v, "invalid attribute name");
+#ifndef _WIN32
+  info->st_blksize = 0; /* never reached */
+#endif
+}
+
+typedef void (*_push_function) (HSQUIRRELVM v, STAT_STRUCT *info);
+
+struct _stat_members {
+	const char *name;
+	_push_function push;
+};
+
+struct _stat_members members[] = {
+	{ "mode",         push_st_mode },
+	{ "dev",          push_st_dev },
+	{ "ino",          push_st_ino },
+	{ "nlink",        push_st_nlink },
+	{ "uid",          push_st_uid },
+	{ "gid",          push_st_gid },
+	{ "rdev",         push_st_rdev },
+	{ "access",       push_st_atime },
+	{ "modification", push_st_mtime },
+	{ "change",       push_st_ctime },
+	{ "size",         push_st_size },
+#ifndef _WIN32
+	{ "blocks",       push_st_blocks },
+	{ "blksize",      push_st_blksize },
+#endif
+	{ NULL, push_invalid }
+};
+
+/*
+** Get file or symbolic link information
+*/
+static int _file_info_ (HSQUIRRELVM v, int (*st)(const SQChar*, STAT_STRUCT*)) {
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 2, file);
+	int i;
+	STAT_STRUCT info;
+
+	if (st(file, &info)) {
+		return sq_throwerror(v, "cannot obtain information from file `%s'", file);
+	}
+	if(_top_ > 2){
+	    int ptype = sq_gettype(v, 3);
+        if (ptype == OT_STRING) {
+            int iv;
+            SQ_GET_STRING(v, 3, member);
+            if (strcmp (member, "mode") == 0) iv = 0;
+#ifndef _WIN32
+            else if (strcmp (member, "blocks")  == 0) iv = 11;
+            else if (strcmp (member, "blksize") == 0) iv = 12;
+#endif
+            else /* look for member */
+                for (iv = 1; members[iv].name; iv++)
+                    if (*members[iv].name == *member)
+                        break;
+            /* push member value and return */
+            members[iv].push (v, &info);
+            return 1;
+        } else if (ptype != OT_TABLE)
+            /* creates a table if none is given */
+            sq_newtable (v);
+	}
+	else sq_newtable (v);
+	/* stores all members in table on top of the stack */
+	for (i = 0; members[i].name; i++) {
+		sq_pushstring (v, members[i].name, -1);
+		members[i].push (v, &info);
+		sq_rawset (v, -3);
+	}
+	return 1;
+}
+
+
+/*
+** Get file information using stat.
+*/
+static int sqfs_attributes (HSQUIRRELVM v) {
+	return _file_info_ (v, STAT_FUNC);
+}
+
+
+/*
+** Get symbolic link information using lstat.
+*/
+#ifndef _WIN32
+static int sqfs_symlinkattributes (HSQUIRRELVM v) {
+	return _file_info_ (v, LSTAT_FUNC);
+}
+#else
+static int sqfs_symlinkattributes (HSQUIRRELVM v) {
+  sq_pushliteral(v, "symlinkattributes not supported on this platform");
+  return 1;
+}
+#endif
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info (HSQUIRRELVM v) {
+	sq_pushliteral (v, "_COPYRIGHT");
+	sq_pushliteral (v, "Copyright (C) Copyright (C) 2003-2012 Kepler Project, Domingo Alvarez Duarte");
+	sq_rawset (v, -3);
+	sq_pushliteral (v, "_DESCRIPTION");
+	sq_pushliteral (v, "LuaFileSystem is a Lua library developed to complement the set of"
+                 " functions related to file systems offered by the standard Lua distribution"
+                 ", adapted to Squirrel by Domingo Alvarez Duarte");
+	sq_rawset (v, -3);
+	sq_pushliteral (v, "_VERSION");
+	sq_pushliteral (v, "LuaFileSystem 1.61");
+	sq_rawset (v, -3);
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sqfs_##name,nparams,tycheck}
+static SQRegFunction sqfs_methods[] =
+{
+	_DECL_FUNC(attributes,  -2, _SC(".ss")),
+	_DECL_FUNC(chdir,  2, _SC(".s")),
+	_DECL_FUNC(currentdir,  1, _SC(".")),
+/*
+	_DECL_FUNC(lock,  -3, _SC("xsii")),
+*/
+	_DECL_FUNC(link,  -3, _SC(".ssb")),
+	_DECL_FUNC(mkdir,  2, _SC(".s")),
+	_DECL_FUNC(rmdir,  2, _SC(".s")),
+	_DECL_FUNC(symlinkattributes,  -2, _SC(".ss")),
+
+//	_DECL_FUNC(setmode,  3, _SC(".ss")),
+	_DECL_FUNC(touch,  -2, _SC(".sii")),
+/*
+	_DECL_FUNC(unlock,  -2, _SC(".sii")),
+	_DECL_FUNC(lock_dir,  -2, _SC(".si")),
+*/
+	{0,0}
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_sqfs(HSQUIRRELVM v)
+    {
+        sq_pushstring(v,_SC("sqfs"),-1);
+        sq_newtable(v);
+        set_info(v);
+        sq_insert_reg_funcs(v, sqfs_methods);
+
+        sq_pushliteral(v, _SC("dir"));
+        sq_newclass(v, SQFalse);
+        sq_settypetag(v,-1,(void*)SQFS_DIR_TAG);
+        sq_insert_reg_funcs(v, _dir_methods);
+
+        sq_pushstring(v, currFileName_key, sizeof(currFileName_key)-1); //store file name between iterations
+        sq_pushnull(v);
+        sq_newslot(v,-3,SQFalse);
+
+        sq_newslot(v,-3,SQTrue);
+
+        sq_newslot(v,-3,SQTrue);
+
+        return 1;
+    }
+
+#ifdef __cplusplus
+}
+#endif

+ 165 - 0
ext/sq_mix.cpp

@@ -0,0 +1,165 @@
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+
+#define MixInteger SQInteger
+#include "code_mix_prep.c"
+
+/* Generic loader function. Load the data found in the state in the lua engine
+ */
+static SQRESULT mix_loadbuffer(HSQUIRRELVM sqvm, mix_state_t *S, const SQChar *name, int isParseOnly) {
+	SQRESULT res;
+	S->pos = 0;
+
+	if (S->size > 0 && S->buffer[0] == '#') {
+		while (S->pos < S->size && S->buffer[S->pos] != '\n')
+			++S->pos;
+		++S->pos;
+		S->token = tok_sh;
+	} else {
+		S->token = tok_code_end;
+	}
+
+	S->error = NULL;
+	if(isParseOnly){
+	    SQBlob blob(0, BLOB_BUFSIZE);
+	    MixInteger ch;
+	    while((ch = sq_mix_reader_char(S))) blob.WriteChar(ch);
+        if (S->error != NULL) {
+            return sq_throwerror(sqvm, S->error);
+        }
+        sq_pushstring(sqvm, (const SQChar*)blob.GetBuf(), blob.Len());
+	}
+	else
+	{
+        res = sq_compile(sqvm, sq_mix_reader_char, S, name, SQTrue);
+        if (S->error != NULL) {
+            return sq_throwerror(sqvm, S->error);
+        } else if (res != 0) {
+            sq_pushnull(sqvm);
+        }
+	}
+	return 1;
+}
+
+SQ_OPT_STRING_STRLEN();
+
+/* Read the options common to mix_loadbuffer and mix_loadfile and store them in
+ * the state.
+ */
+static SQRESULT mix_stateopt(HSQUIRRELVM sqvm, mix_state_t *S) {
+    SQ_FUNC_VARS(sqvm);
+
+	SQ_OPT_STRING(sqvm, 3, code_start, "<?");
+	S->code_start = code_start;
+	S->code_startsize = code_start_size;
+	if (S->code_startsize == 0)
+		return sq_throwerror(sqvm, _SC("code_start separator cannot be empty"));
+
+	SQ_OPT_STRING(sqvm, 4, code_end, "?>");
+	S->code_end = code_end;
+	S->code_endsize = code_end_size;
+	if (S->code_endsize == 0)
+		return sq_throwerror(sqvm, _SC("code_end separator cannot be empty"));
+
+	SQ_OPT_STRING(sqvm, 5, expr_code, "=");
+	S->expr = expr_code;
+	S->exprsize = expr_code_size;
+    if (S->exprsize == 0)
+            return sq_throwerror(sqvm, _SC("expr separator cannot be empty"));
+
+	SQ_OPT_STRING(sqvm, 6, print_code, "mix_write");
+    if (print_code_size == 0)
+            return sq_throwerror(sqvm, _SC("mix_write function name cannot be empty"));
+
+
+    snprintf(S->print_out, sizeof(S->print_out), "%s(\"", print_code);
+	S->print_outsize = strlen(S->print_out);
+	S->result_size = 0;
+	return 0;
+}
+
+static SQRESULT mix_load_parse_file(HSQUIRRELVM sqvm, int isParse) {
+	const SQChar  *filename;
+	FILE        *file;
+	mix_state_t  S;
+    sq_mix_init(&S, 0, 0, 0,0,0,0);
+
+	sq_getstring(sqvm, 2, &filename);
+	SQRESULT rc = mix_stateopt(sqvm, &S);
+	if(rc) return rc;
+
+	file = fopen(filename, _SC("r"));
+	if (file == NULL) {
+		return sq_throwerror(sqvm, _SC("cannot open file <%s>"), filename);
+	}
+
+	fseek(file, 0, SEEK_END);
+	S.size = ftell(file);
+	fseek(file, 0, SEEK_SET);
+
+	SQBlob buffer(0, S.size);
+	if (fread(buffer.GetBuf(), S.size, 1, file) != 1) {
+		fclose(file);
+		return sq_throwerror(sqvm, _SC("cannot read file <%s>"), filename);
+	}
+	S.buffer = (const char*)buffer.GetBuf();
+	fclose(file);
+
+	return mix_loadbuffer(sqvm, &S, filename, isParse);
+}
+
+static SQRESULT mix_loadfile(HSQUIRRELVM sqvm) {
+    return mix_load_parse_file(sqvm, 0);
+}
+
+static SQRESULT mix_parsefile(HSQUIRRELVM sqvm) {
+    return mix_load_parse_file(sqvm, 1);
+}
+
+static SQRESULT mix_load_parse_string(HSQUIRRELVM sqvm, int isParse) {
+	mix_state_t S;
+	sq_mix_init(&S, 0, 0, 0,0,0,0);
+
+	sq_getstring(sqvm, 2, &S.buffer);
+	S.size = sq_getsize(sqvm, 2);
+	mix_stateopt(sqvm, &S);
+
+	return mix_loadbuffer(sqvm, &S, "chunk", isParse);
+}
+
+static SQRESULT mix_loadstring(HSQUIRRELVM sqvm) {
+    return mix_load_parse_string(sqvm, 0);
+}
+
+static SQRESULT mix_parsestring(HSQUIRRELVM sqvm) {
+    return mix_load_parse_string(sqvm, 1);
+}
+
+const SQChar validate_format_mask[] = _SC(".s s|o s|o s|o s");
+#define _DECL_MIX_FUNC(name,nparams,pmask) {_SC(#name), mix_##name,nparams,pmask}
+static SQRegFunction mix_obj_funcs[]={
+	_DECL_MIX_FUNC(parsefile,-2,validate_format_mask),
+	_DECL_MIX_FUNC(parsestring,-2,validate_format_mask),
+	_DECL_MIX_FUNC(loadfile,-2,validate_format_mask),
+	_DECL_MIX_FUNC(loadstring,-2,validate_format_mask),
+	{0,0}
+};
+#undef _DECL_MIX_FUNC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* This defines a function that opens up your library. */
+SQRESULT sqext_register_mix (HSQUIRRELVM sqvm) {
+    //add a namespace sqmix
+	sq_pushstring(sqvm,_SC("sqmix"),-1);
+	sq_newclass(sqvm,SQFalse);
+    sq_insert_reg_funcs(sqvm, mix_obj_funcs);
+	sq_newslot(sqvm,-3,SQTrue); //add sqmix table to the root table
+
+	return SQ_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 1275 - 0
ext/sq_mongoose.cpp

@@ -0,0 +1,1275 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+SQ_OPT_STRING_STRLEN();
+
+#ifdef USE_SQ_SQLITE3
+#include "lsqlite3.h"
+#endif
+
+#ifdef USE_AXTLS
+#ifdef __cplusplus
+extern "C" {
+#endif
+    void * SSL_CTX_new(void *);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#define USE_MG_MD5 1
+
+#include "mongoose.h"
+
+#define PRINT_FILE_LINE printf("%s %d\n", __FILE__,__LINE__);
+
+#ifdef UNUSED
+#elif defined(__GNUC__)
+# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+#elif defined(__LCLINT__)
+# define UNUSED(x) /*@unused@*/ x
+#else
+# define UNUSED(x) x
+#endif
+
+#define MARK()  do { \
+    printf("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__); \
+} while (0)
+
+typedef struct SQ_Mg_Context SQ_Mg_Context;
+typedef struct SQ_MG_Callback SQ_MG_Callback;
+
+struct SQ_MG_Callback {
+    size_t size;
+    char buf[1];
+};
+
+static SQ_MG_Callback *SQ_MG_Callback_malloc(size_t x){
+    SQ_MG_Callback *p = (SQ_MG_Callback *)sq_malloc(sizeof(SQ_MG_Callback)+x);
+    if(p) p->size = x;
+    return p;
+}
+
+static void SQ_MG_Callback_free(SQ_MG_Callback *p){
+    if(p) sq_free(p, sizeof(SQ_MG_Callback)+p->size);
+}
+
+struct SQ_Mg_Context {
+    HSQUIRRELVM v;
+    struct mg_context *ctx;
+    SQ_MG_Callback *master_plugin;
+    SQ_MG_Callback *master_plugin_exit;
+    SQ_MG_Callback *user_callback;
+    SQ_MG_Callback *user_callback_setup;
+    SQ_MG_Callback *user_callback_exit;
+};
+
+static const SQChar sq_mg_context_TAG[] = "sq_mg_conn_class";
+#define GET_mg_context_INSTANCE() \
+    SQ_Mg_Context *self; \
+    if((_rc_ = sq_getinstanceup(v,1,(SQUserPointer*)&self,(void*)sq_mg_context_TAG)) < 0) return _rc_;
+
+static const SQChar sq_mg_user_callback[] = "mg_user_callback";
+
+static const SQChar sq_http_request_TAG[] = "HttpRequest";
+
+#define GET_http_request_INSTANCE() \
+    struct mg_connection *conn; \
+    if((_rc_ = sq_getinstanceup(v,1,(SQUserPointer*)&conn,(void*)sq_http_request_TAG)) < 0) return _rc_;
+
+static SQRESULT sq_http_request_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	return 1;
+}
+
+static SQRESULT sq_http_request_constructor(HSQUIRRELVM v)
+{
+    //SQ_FUNC_VARS_NO_TOP(v);
+    struct mg_connection *conn = 0;
+
+    sq_setinstanceup(v, 1, conn);
+    sq_setreleasehook(v,1, sq_http_request_releasehook);
+	return 1;
+}
+
+static SQRESULT
+sq_http_request_print(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    GET_http_request_INSTANCE();
+    SQInteger i, write_count = 0;
+
+    for (i = 2; i <= _top_; ++i) {
+        sq_tostring(v, i);
+        SQ_GET_STRING(v, -1, value);
+        write_count += mg_write(conn, value, value_size);
+        sq_poptop(v);
+    }
+
+    sq_pushinteger(v, write_count);
+    return 1;
+}
+
+#ifdef USE_SQ_LSQLITE3
+static SQRESULT
+sq_http_request_vm_print(HSQUIRRELVM v)
+{
+    GET_http_request_INSTANCE();
+    lsqlite3_sdb_vm *svm = (lsqlite3_sdb_vm *)luaL_checkudata(v, 1,
+                                                              lsqlite3_sqlite_vm_meta);
+    SQInteger idx = luaL_checkint(v,2);
+
+    SQInteger len = sqlite3_column_bytes(svm->vm, idx);
+    if(len) sq_pushinteger(v, mg_write(conn, sqlite3_column_text(svm->vm, idx), len));
+    else sq_pushinteger(v, 0);
+    return 1;
+}
+#endif
+
+static SQRESULT
+sq_http_request_write(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, buf);
+    SQ_OPT_INTEGER(v, 3, write_size, buf_size);
+    sq_pushinteger(v, mg_write(conn, buf, write_size));
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_read(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    GET_http_request_INSTANCE();
+    SQ_OPT_INTEGER(v, 2, n, 1024*2000);
+    size_t rlen;  /* how much to read */
+    size_t nr;  /* number of chars actually read */
+    rlen = 8192;  /* try to read that much each time */
+
+    SQBlob blob(0, rlen);
+    if (rlen > n) rlen = n;  /* cannot read more than asked */
+    char *p = sq_getscratchpad(v,rlen);
+    do {
+        nr = mg_read(conn, p, rlen);
+        blob.Write(p, nr);
+        n -= nr;  /* still have to read `n' chars */
+    } while (n > 0 && nr == rlen);  /* until end of count or eof */
+    sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len());  /* close buffer */
+
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_send_file(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, file_path);
+    mg_send_file(conn, file_path);
+    return 0;
+}
+
+static SQRESULT
+sq_http_request_write_blob(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+	SQBlob *blob = NULL;
+	{ if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&blob,(SQUserPointer)SQBlob::SQBlob_TAG)))
+		return sq_throwerror(v,_SC("invalid type tag"));  }
+	if(!blob || !blob->IsValid())
+		return sq_throwerror(v,_SC("the blob is invalid"));
+
+    sq_pushinteger(v, mg_write(conn, (const SQChar*)blob->GetBuf(), blob->Len()));
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_get_header(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, name);
+    sq_pushstring(v, mg_get_header(conn, name), -1);
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_get_cookie(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, cookie_name);
+
+    const char *start;
+    int len = mg_find_cookie(conn, cookie_name, &start);
+
+    if(len > 0) sq_pushstring(v, start, len);
+    else sq_pushnull(v);
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_get_var(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, data);
+    SQ_GET_STRING(v, 3, name);
+
+    const char *start;
+    size_t buffer_len;
+    int var_len = mg_find_var(data, data_size, name, &start);
+    if(var_len > 0){
+        buffer_len = var_len+1;
+        char *buffer = sq_getscratchpad(v,buffer_len);
+        if(buffer){
+            var_len = mg_url_decode(start, var_len, buffer, buffer_len, 1);
+            sq_pushstring(v, buffer, var_len);
+            return 1;
+        }
+    }
+    sq_pushnull(v);
+    return 1;
+}
+
+static SQRESULT
+sq_http_request_handle_cgi_request(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, prog);
+
+    mg_handle_cgi_request(conn, prog);
+
+    return 0;
+}
+
+static SQRESULT
+sq_http_request_get_option(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, name);
+    SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) mg_get_user_data(conn);
+    sq_pushstring(v, mg_get_option(sq_mg_ctx->ctx, name), -1);
+
+    return 1;
+}
+
+//Digest authentication functions
+#define MAX_USER_LEN  20
+#define MAX_NONCE_LEN  36 //extra bytes for zero terminator
+#define MAX_SESSIONS 5
+#define SESSION_TTL 3600
+#define SESSION_REQUEST_TTL 120
+
+enum e_session_state {e_session_invalid, e_session_sent_request, e_session_authorized};
+
+struct st_session_t
+{
+    int state;
+    char nonce[MAX_NONCE_LEN];
+    char user[MAX_USER_LEN];         // Authenticated user
+    long last_nc;
+    time_t last_access;       // last_access time
+    long remote_ip;           // Client's IP address
+};
+
+static struct st_session_t sessions[MAX_SESSIONS];  // Current sessions
+
+// Protects messages, sessions, last_message_id
+static mg_thread_mutex_t session_rwlock;
+
+//should be called only after locking session_rwlock
+static struct st_session_t *my_get_session_only_after_lock(const char *nonce){
+    int i;
+    for(i=0; i < MAX_SESSIONS; ++i){
+        //printf("%s : %s\n", sessions[i].nonce, ah->nonce);
+        if(strcmp(sessions[i].nonce, nonce) == 0){
+            return &sessions[i];
+        }
+    }
+    return 0;
+}
+
+// Check the user's password, return 1 if OK
+static SQBool my_check_password(const struct mg_request_info *request_info, const char *my_tmp_password)
+{
+    md5_buf_t ha2, expected_response;
+    struct mg_auth_header *ah = request_info->ah;
+
+    // Some of the parameters may be NULL
+    if (request_info->request_method == NULL ||
+            //strcmp(ri->request_method, "PUT") == 0 ||
+            //strcmp(ri->request_method, "DELETE") == 0 ||
+            ah == NULL ||
+            ah->nonce == NULL || ah->nc == NULL ||
+            ah->cnonce == NULL || ah->qop == NULL || ah->uri == NULL ||
+            ah->response == NULL)
+    {
+        return SQFalse;
+    }
+
+    // NOTE(lsm): due to a bug in MSIE, we do not compare the URI
+    // TODO(lsm): check for authentication timeout
+    if (// strcmp(ah->uri, conn->request_info.uri) != 0 ||
+        strlen(ah->response) != 32
+    )
+    {
+        return SQFalse;
+    }
+
+    mg_md5(ha2, request_info->request_method, ":", ah->uri, NULL);
+    mg_md5(expected_response, my_tmp_password /*ah->ha1*/, ":", ah->nonce, ":", ah->nc,
+           ":", ah->cnonce, ":", ah->qop, ":", ha2, NULL);
+    SQBool result = mg_strcasecmp(ah->response, expected_response) == 0;
+    //printf("%s : %s : %s\n", my_tmp_password, ah->response, expected_response);
+
+    if(result)  //lets check timeout and other issues
+    {
+        struct st_session_t *session_found = 0;
+        result = SQFalse;
+
+        mg_thread_mutex_lock(&session_rwlock);
+
+        session_found = my_get_session_only_after_lock(ah->nonce);
+        if(session_found)
+        {
+            do
+            {
+                //mobile ip is a pain for security
+                if( /*(ses.remote_ip != request_info->remote_ip) ||*/
+                        ((time(NULL) - session_found->last_access) > SESSION_TTL)
+                  ) break;
+                if(session_found->state == e_session_sent_request)
+                {
+                    session_found->state = e_session_authorized;
+                    snprintf(session_found->user, sizeof(session_found->user), "%s", ah->user);
+                }
+                else if(strcmp(session_found->user, ah->user) != 0) break;
+
+                long recived_nc = strtol(ah->nc, 0, 16);
+                time_t received_time = time(NULL);
+/*
+//printf("%d : %lu : %lu : %lu : %lu\n", request_info->remote_port, ses.last_nc, recived_nc, ses.last_access, received_time);
+                if((ses.last_nc+1) != recived_nc){
+                    //lets see if we can manage out of order sent by some browsers
+                    if((received_time - ses.last_access) > 2) break;
+                    //inside a window of 2 seconds we tolerate nc out of order
+                    if(ses.last_nc > recived_nc) recived_nc = ses.last_nc;
+                }
+*/
+                session_found->last_access = received_time;
+                session_found->last_nc = recived_nc;
+                result = SQTrue;
+            } while(0);
+
+            if(!result){
+                session_found->state = e_session_invalid;
+                session_found->nonce[0] = '\0';
+            }
+       }
+       else {
+           //dbg_msg("Session not found ! : %s : %s\n", ah->nonce, request_info->uri);
+       }
+
+        mg_thread_mutex_unlock(&session_rwlock);
+    }
+
+    return result;
+}
+
+static SQRESULT
+sq_http_request_check_password(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, my_tmp_password);
+    const struct mg_request_info *request_info = mg_get_request_info(conn);
+    sq_pushbool(v, my_check_password(request_info, my_tmp_password));
+    return 1;
+}
+
+// Close user session return 1 if closed
+static SQBool my_close_session(const struct mg_request_info *request_info)
+{
+    SQBool result = SQFalse;
+    struct st_session_t *session_found = 0;
+    struct mg_auth_header *ah = request_info->ah;
+
+    // Some of the parameters may be NULL
+    if (request_info->request_method == NULL ||
+            //strcmp(ri->request_method, "PUT") == 0 ||
+            //strcmp(ri->request_method, "DELETE") == 0 ||
+            ah == NULL ||
+            ah->nonce == NULL || ah->nc == NULL ||
+            ah->cnonce == NULL || ah->qop == NULL || ah->uri == NULL ||
+            ah->response == NULL)
+    {
+        return 0;
+    }
+
+    mg_thread_mutex_lock(&session_rwlock);
+
+    session_found = my_get_session_only_after_lock(ah->nonce);
+    if(session_found) {
+        session_found->state = e_session_invalid;
+        session_found->nonce[0] = '\0';
+        result = SQTrue;
+    }
+    mg_thread_mutex_unlock(&session_rwlock);
+    return result;
+}
+
+static SQRESULT
+sq_http_request_close_session(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    const struct mg_request_info *request_info = mg_get_request_info(conn);
+    sq_pushbool(v, my_close_session(request_info));
+    return 1;
+}
+
+typedef char buf_1024_t[1024];
+
+static const char *my_encode_nonce(buf_1024_t buf, md5_buf_t md5_buf, unsigned long ip)
+{
+    snprintf(buf, sizeof(buf), "%lu:%d:%d:%lu", (unsigned long) time(NULL), rand(), rand(), ip);
+    mg_md5(md5_buf, buf, NULL);
+    return md5_buf;
+}
+
+static void my_send_authorization_request(struct mg_connection *conn,
+        const struct mg_request_info *request_info,
+        const char *authentication_domain,
+        const char *nonce)
+{
+    md5_buf_t md5_buf;
+    buf_1024_t buf;
+    int i;
+    if (nonce == NULL)
+    {
+        nonce = my_encode_nonce(buf, md5_buf, (unsigned long) request_info->remote_ip);
+    }
+    struct st_session_t *available_session = NULL;
+
+    mg_thread_mutex_lock(&session_rwlock);
+
+    for(i=0; i<3; ++i)
+    {
+        for(i=0; i < MAX_SESSIONS; ++i){
+            if(sessions[i].state == e_session_invalid){
+                available_session = &sessions[i];
+            }
+            if(sessions[i].state == e_session_sent_request){
+                if((time(NULL) - available_session->last_access) > SESSION_REQUEST_TTL){
+                    //if session request bigger than 2 minutes reuse it
+                    available_session = &sessions[i];
+                }
+            }
+        }
+
+        if(available_session){
+            available_session->state = e_session_sent_request;
+            available_session->last_access = time(NULL);
+            available_session->last_nc = 0;
+            available_session->remote_ip = request_info->remote_ip;
+            snprintf(available_session->nonce, sizeof(available_session->nonce),
+                     "%s", nonce);
+            break;
+        }
+        else
+        {
+            nonce = my_encode_nonce(buf, md5_buf, (unsigned long) request_info->remote_ip);
+        }
+    }
+
+    mg_thread_mutex_unlock(&session_rwlock);
+
+    if(available_session) {
+        i = snprintf(buf, sizeof(buf),
+            "HTTP/1.1 401 Unauthorized\r\n"
+            "Content-Length: 0\r\n"
+            "WWW-Authenticate: Digest qop=\"auth\", "
+            "realm=\"%s\", nonce=\"%s\"\r\n\r\n",
+            authentication_domain, nonce);
+    } else {
+        i = snprintf(buf, sizeof(buf),
+            "HTTP/1.1 503 Service Temporary Unavailable\r\n"
+            "Content-Length: 0\r\n\r\n");
+    }
+
+    mg_write(conn, buf, i);
+}
+
+static SQRESULT
+sq_http_request_send_authorization_request(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_http_request_INSTANCE();
+    SQ_GET_STRING(v, 2, authentication_domain);
+    const struct mg_request_info *request_info = mg_get_request_info(conn);
+    my_send_authorization_request(conn, request_info, authentication_domain, NULL);
+    return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_http_request_##name,nparams,tycheck}
+static SQRegFunction mg_http_request_methods[] =
+{
+	_DECL_FUNC(constructor,  1, _SC("x")),
+
+	_DECL_FUNC(print,  -2, _SC("x n|s")),
+	_DECL_FUNC(read,  2, _SC("xi")),
+	_DECL_FUNC(write,  3, _SC("xsi")),
+	_DECL_FUNC(write_blob,  -2, _SC("xxi")),
+	_DECL_FUNC(get_var,  3, _SC("xs")),
+	_DECL_FUNC(get_cookie,  2, _SC("xs")),
+	_DECL_FUNC(get_header,  2, _SC("xs")),
+	_DECL_FUNC(send_file,  2, _SC("xs")),
+	_DECL_FUNC(handle_cgi_request,  2, _SC("xs")),
+	_DECL_FUNC(get_option,  2, _SC("xs")),
+	_DECL_FUNC(check_password,  2, _SC("xs")),
+	_DECL_FUNC(close_session,  1, _SC("x")),
+	_DECL_FUNC(send_authorization_request,  2, _SC("xs")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+/***********/
+
+// helper function to extract a single mg_config value from a Lua table
+static void
+fetchfield(HSQUIRRELVM v, int idx, const char *key, char **value, const char *d)
+{
+    const char *s;
+    sq_pushstring(v, key, -1);
+    if(sq_rawget(v, idx) == SQ_OK){
+        if(sq_gettype(v, -1) != OT_NULL){
+            sq_tostring(v, -1);
+            sq_getstring(v, -1, &s);
+            *value = mg_strdup(s);
+            sq_pop(v, 2); //retrieved value and converted value
+            return;
+        }
+    }
+    *value = NULL;
+}
+
+// initializes an options string array from a Lua table
+static SQRESULT
+fetchoptions(HSQUIRRELVM v, int idx, const char **options)
+{
+    struct {
+        const char *key;
+        const char *value;
+    } OPTIONS[] = {
+        { "cgi_extensions", ".cgi,.pl,.php" },
+        { "cgi_environment", NULL },
+        { "put_delete_passwords_file", NULL },
+        { "cgi_interpreter", NULL },
+        { "protect_uri", NULL },
+        { "authentication_domain", "mydomain.com" },
+        { "ssi_extensions", ".shtml,.shtm" },
+        { "access_log_file", NULL },
+        { "ssl_chain_file", NULL },
+        { "enable_directory_listing", "yes" },
+        { "error_log_file", NULL },
+        { "global_passwords_file", NULL },
+        { "index_files", "index.html,index.htm,index.cgi" },
+        { "enable_keep_alive", "no" },
+        { "access_control_list", NULL },
+        { "max_request_size", "16384" },
+        { "extra_mime_types", NULL },
+        { "listening_ports", "8080" },
+        { "document_root",  "." },
+        { "ssl_certificate", NULL },
+        { "num_threads", "10" },
+        { "run_as_user", NULL },
+        { NULL, NULL }
+    };
+    char *value;
+    int i, j;
+
+    if(sq_gettype(v, idx) != OT_TABLE) return sq_throwerror(v, "a table is needed to retrieve options");
+
+    for (i = 0, j = 0; OPTIONS[i].key; ++i) {
+        fetchfield(v, idx, OPTIONS[i].key, &value, OPTIONS[i].value);
+        if (NULL != value) {
+            options[j++] = mg_strdup(OPTIONS[i].key);
+            options[j++] = value;
+        }
+    }
+    options[j] = NULL;
+    return 0;
+}
+
+/***********/
+
+static const char sq_mongoose_TAG[] = "Mongoose";
+static SQBool show_errors_on_stdout = SQFalse;
+
+static void sq_mongoose_release_references(SQ_Mg_Context *self){
+    SQ_MG_Callback_free(self->master_plugin);
+    SQ_MG_Callback_free(self->master_plugin_exit);
+    SQ_MG_Callback_free(self->user_callback);
+    SQ_MG_Callback_free(self->user_callback_setup);
+    SQ_MG_Callback_free(self->user_callback_exit);
+}
+
+static SQRESULT sq_mongoose_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+    SQ_Mg_Context *self = (SQ_Mg_Context *)p;
+    if(self){
+        if(self->ctx){
+            mg_stop(self->ctx);
+            sq_mongoose_release_references(self);
+            self->ctx = 0;
+        }
+        sq_free(self, sizeof(SQ_Mg_Context));
+    }
+	return 0;
+}
+
+static SQRESULT sq_mongoose_constructor(HSQUIRRELVM v)
+{
+    //SQ_FUNC_VARS_NO_TOP(v);
+    SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *)sq_malloc(sizeof(SQ_Mg_Context));
+    memset(sq_mg_ctx, 0, sizeof(SQ_Mg_Context));
+
+    sq_setinstanceup(v, 1, sq_mg_ctx);
+    sq_setreleasehook(v,1, sq_mongoose_releasehook);
+	return 1;
+}
+
+#define GET_mongoose_INSTANCE() \
+    SQ_Mg_Context *self; \
+    if((_rc_ = sq_getinstanceup(v,1,(SQUserPointer*)&self,(void*)sq_mongoose_TAG)) < 0) return _rc_;
+
+static SQRESULT
+sq_mongoose_show_errors_on_stdout(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_BOOL(v, 2, onOff);
+    show_errors_on_stdout = onOff;
+    return 0;
+}
+
+static SQRESULT
+sq_mongoose_modify_passwords_file(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	SQ_GET_STRING(v, 2, passwords_file_name);
+	SQ_GET_STRING(v, 3, domain);
+	SQ_GET_STRING(v, 4, user);
+	SQ_GET_STRING(v, 5, password);
+
+    sq_pushinteger(v, mg_modify_passwords_file(passwords_file_name,
+                             domain, user, password));
+    return 1;
+}
+
+static SQRESULT
+sq_mongoose_version(HSQUIRRELVM v)
+{
+    sq_pushstring(v, mg_version(), -1);
+    return 1;
+}
+
+SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
+// creates a reference dispatching callbacks to squirrel functions
+static SQRESULT
+fetchcallback(HSQUIRRELVM v, const char *key, SQ_MG_Callback **sq_cb)
+{
+    if(!sq_cb) return sq_throwerror(v, "inavlid SQ_MG_Callback parameter value (NULL)");
+    if(sq_gettype(v, -1) != OT_TABLE) return sq_throwerror(v, "table expected to fetch callbacks");
+    sq_pushstring(v, key, -1);
+    sq_rawget(v, -2);
+
+    if (sq_gettype(v, -1) == OT_CLOSURE){
+        SQBlob b(0,8192);
+        if(SQ_SUCCEEDED(sq_writeclosure(v,blob_write,&b))) {
+            *sq_cb = SQ_MG_Callback_malloc(b.Len());
+            if(*sq_cb) memcpy((*sq_cb)->buf, b.GetBuf(), b.Len());
+            sq_poptop(v);
+        }
+    }
+    else
+    {
+        sq_pop(v, 1);
+        return sq_throwerror(v, "closure expected for callbacks");
+    }
+    return SQ_OK;
+}
+
+static void *
+user_callback_proxy(enum mg_event event,
+                    struct mg_connection *conn,
+                    const struct mg_request_info *ri);
+
+// creates a new server using a configuration table
+static SQRESULT
+sq_mongoose_start(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_mongoose_INSTANCE();
+	_rc_ = 1; //assumes succeed
+
+    const char *options[64];
+    SQInteger i;
+
+    if(self->ctx) return sq_throwerror(v, _SC("mongoose already running or stoped incorrectly"));
+
+    // store the Squirrel vm for use in callback proxies
+    self->v = v;
+
+    // prepare the mg_config structure from the squirrel table argument
+    memset(options, 0, sizeof (options));
+    fetchoptions(v, 2, options);
+
+    fetchcallback(v, "master_plugin", &self->master_plugin);
+    fetchcallback(v, "master_plugin_exit", &self->master_plugin_exit);
+
+    fetchcallback(v, "user_callback", &self->user_callback);
+    fetchcallback(v, "user_callback_setup", &self->user_callback_setup);
+    fetchcallback(v, "user_callback_exit", &self->user_callback_exit);
+
+    self->ctx = mg_start(user_callback_proxy, self, options);
+
+    // free the options string list memory
+    for (i = 0; options[i]; ++i)
+        free((void *) options[i]);
+
+    // throw an error if the server did not start
+    if (self->ctx == NULL) {
+        sq_mongoose_release_references(self);
+        _rc_ = sq_throwerror(v, "could not start mongoose");
+    }
+
+    // return the context so it can be stopped later
+    return _rc_;
+}
+
+static SQRESULT
+sq_mongoose_stop(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_mongoose_INSTANCE();
+
+    if(self->ctx){
+        mg_stop(self->ctx);
+        sq_mongoose_release_references(self);
+        self->ctx = 0;
+    }
+
+    return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_mongoose_##name,nparams,tycheck}
+static SQRegFunction sq_mongoose_methods[] =
+{
+	_DECL_FUNC(constructor,  1, _SC("x")),
+
+	_DECL_FUNC(start,  -1, _SC("x")),
+	_DECL_FUNC(stop,  1, _SC("x")),
+	_DECL_FUNC(modify_passwords_file,  1, _SC("x")),
+	_DECL_FUNC(version,  1, _SC("x")),
+	_DECL_FUNC(show_errors_on_stdout,  2, _SC("xb")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+static SQRESULT
+sq_mg_url_decode_base(HSQUIRRELVM v, SQInteger is_form_url_encoded)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, src);
+
+    int dst_len = src_size +1;
+    char *dst = sq_getscratchpad(v,dst_len);
+    dst_len = mg_url_decode(src, src_size, dst, dst_len, is_form_url_encoded);
+    sq_pushstring(v, dst, dst_len);
+    return 1;
+}
+
+static SQRESULT
+sq_mg_url_decode(HSQUIRRELVM v)
+{
+    return sq_mg_url_decode_base(v, 1);
+}
+
+static SQRESULT
+sq_mg_uri_decode(HSQUIRRELVM v)
+{
+    return sq_mg_url_decode_base(v, 0);
+}
+
+static SQRESULT
+sq_mg_url_encode(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, src);
+
+    char *dst = mg_url_encode(src);
+
+    sq_pushstring(v, dst, -1);
+    free(dst);
+    return 1;
+}
+
+static SQRESULT
+sq_mg_md5(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS(v);
+
+    char buf[32 + 1];
+    unsigned char hash[16];
+    MD5_CTX ctx;
+    MD5Init(&ctx);
+
+    for (int i = 2; i <= _top_; ++i) {
+        SQ_GET_STRING(v, i, p);
+        MD5Update(&ctx, (const unsigned char *) p, p_size);
+    }
+
+    MD5Final(hash, &ctx);
+    mg_bin2str(buf, hash, sizeof(hash));
+    sq_pushstring(v, buf, -1);
+    return 1;
+}
+
+static SQRESULT
+sq_mg_debug_print(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SQInteger i, write_count = 0;
+
+    for (i = 2; i <= _top_; ++i) {
+        sq_tostring(v, i);
+        SQ_GET_STRING(v, -1, value);
+        write_count += fwrite(value, 1, value_size, stderr);
+        sq_poptop(v);
+    }
+
+    sq_pushinteger(v, write_count);
+    return 1;
+}
+
+#ifdef JNI_ENABLE_LOG
+#include <android/log.h>
+
+/*
+** A callback for the android_log() SQIntegererface.
+*/
+static void jniLog(int iErrCode, const char *zMsg){
+  __android_log_print(ANDROID_LOG_ERROR,"jniLuaServerLog","(%d) %s\n", iErrCode, zMsg);
+}
+
+static SQRESULT sq_mg_jniLog(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_INTEGER(v, 2, code);
+    SQ_GET_STRING(v, 3, error_message);
+    jniLog(code, error_message);
+    return 0;
+}
+#endif
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_mg_##name,nparams,tycheck, SQTrue}
+static SQRegFunction sq_mg_methods[] =
+{
+	_DECL_FUNC(url_decode,  2, _SC(".s")),
+	_DECL_FUNC(uri_decode,  2, _SC(".s")),
+	_DECL_FUNC(url_encode,  2, _SC(".s")),
+	_DECL_FUNC(md5,  -2, _SC(".s")),
+#ifdef JNI_ENABLE_LOG
+	_DECL_FUNC(jniLog,  -2, _SC(".s")),
+#endif
+	_DECL_FUNC(debug_print,  -2, _SC(".s")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+static void reg_string(HSQUIRRELVM v, const char *name, const char *val) {
+  sq_pushstring(v, name, -1);
+  if(val) sq_pushstring(v, val, -1);
+  else sq_pushnull(v);
+  sq_rawset(v, -3);
+}
+
+static void reg_integer(HSQUIRRELVM v, const char *name, int val) {
+  sq_pushstring(v, name, -1);
+  sq_pushinteger(v, val);
+  sq_rawset(v, -3);
+}
+
+// pushes request info on the Lua stack as a table
+static void
+push_request(HSQUIRRELVM v, const struct mg_request_info *ri)
+{
+    int i;
+
+    sq_pushliteral(v, _SC("info"));
+    sq_get(v, -2);
+#define NEWSLOT_STR(ks) reg_string(v, #ks, ri->ks);
+    NEWSLOT_STR(request_method);
+    NEWSLOT_STR(uri);
+    NEWSLOT_STR(http_version);
+    NEWSLOT_STR(query_string);
+    NEWSLOT_STR(remote_user);
+    NEWSLOT_STR(log_message);
+#define NEWSLOT_INT(ks) reg_integer(v, #ks, ri->ks);
+    NEWSLOT_INT(remote_ip);
+    NEWSLOT_INT(remote_port);
+    NEWSLOT_INT(status_code);
+    NEWSLOT_INT(is_ssl);
+#undef NEWSLOT_STR
+#undef NEWSLOT_INT
+
+    sq_pushliteral(v, "http_headers");
+    sq_newtable(v);
+    for (i = 0; i < ri->num_headers; ++i) {
+        reg_string(v, ri->http_headers[i].name, ri->http_headers[i].value);
+    }
+    sq_newslot(v, -3, SQFalse);
+    sq_poptop(v); //remove data table
+}
+
+static SQInteger
+sq_mg_pcall_master_plugin(HSQUIRRELVM v)
+{
+#if 0
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_MG_CONNECION();
+    SQ_GET_STRING(v, 2, func_name);
+    const SQChar *error_message = _SC("No master plugin installed !");
+    HSQUIRRELVM master_plugin = (HSQUIRRELVM) mg_lock_master_plugin(conn);
+    if(master_plugin){
+        int master_plugin_saved_top = sq_gettop(master_plugin);
+        //sq_pushcfunction(master_plugin, traceback);  /* push traceback function */
+        //int error_func = sq_gettop(master_plugin);
+
+        sq_pushstring(master_plugin, func_name, func_name_size);
+        sq_getonroottable(master_plugin);
+        if(sq_gettype(master_plugin, -1) == OT_CLOSURE){
+            sq_pushroottable(master_plugin);
+            int arg_top = sq_gettop (v);
+            /* Push arguments to dst stack */
+            int idx = 4;
+            copy_values_between_vms (master_plugin, v, arg_top-idx, idx);
+            if (sq_pcall (master_plugin, arg_top-idx+1, SQTrue, SQTrue) == SQ_OK) {
+              /* run OK? */
+              int ret_top = sq_gettop (master_plugin);
+              /* Push status = OK */
+              sq_pushbool (v, SQTrue);
+              /* Return values to src */
+              //copy_values_between_vms (v, master_plugin, master_plugin_saved_top+2, ret_top);
+              /* pops debug.traceback and result from dst state */
+              //sq_settop(master_plugin, master_plugin_saved_top);
+              /*unlock master plugin*/
+              mg_unlock_master_plugin(conn);
+              /* Return true (success) plus return values */
+              return 1;
+            }
+            error_message = sq_tostring (master_plugin, -1);
+        } else error_message = "Attempt to call an invalid function on master plugin !";
+
+        /* pops debug.traceback and result from dst state */
+        sq_settop(master_plugin, master_plugin_saved_top);
+        /*unlock master plugin*/
+        mg_unlock_master_plugin(conn);
+    }
+
+    return sq_throwerror(v, error_message);
+#endif
+}
+
+static void write_error_message(struct mg_connection *conn,
+                        const char * error_msg, SQInteger error_len){
+#define PRE_TAG_OPEN "<pre>"
+#define PRE_TAG_CLOSE "</pre>"
+    mg_write(conn, PRE_TAG_OPEN, sizeof(PRE_TAG_OPEN));
+    if(error_len < 0) error_len = strlen(error_msg);
+    mg_write(conn, error_msg, error_len);
+    mg_write(conn, PRE_TAG_CLOSE, sizeof(PRE_TAG_CLOSE));
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+SQUIRREL_API SQRESULT sqext_register_SQLite3(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqext_register_base64(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqext_register_mix(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
+SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqext_register_Sq_Fpdf(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqext_register_sqfs(HSQUIRRELVM v);
+SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);
+SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sqext_register_sq_socket(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+void sq_printfunc(HSQUIRRELVM v,const SQChar *s,...)
+{
+	va_list vl;
+	va_start(vl, s);
+	vfprintf(stdout, s, vl);
+	va_end(vl);
+}
+
+void sq_errorfunc(HSQUIRRELVM v,const SQChar *s,...)
+{
+	va_list vl;
+	va_start(vl, s);
+	vfprintf(stderr, s, vl);
+	va_end(vl);
+}
+
+#define INT_CONST(v,num) 	sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue);
+
+static HSQUIRRELVM my_new_squirrel(struct mg_context *ctx) {
+    HSQUIRRELVM v = sq_open(1024);
+    if(!v) return 0;
+
+	sqstd_seterrorhandlers(v); //registers the default error handlers
+	sq_setprintfunc(v, sq_printfunc, sq_errorfunc); //sets the print function
+
+    sq_pushroottable(v);
+
+	sqstd_register_bloblib(v);
+	sqstd_register_iolib(v);
+	sqstd_register_systemlib(v);
+	sqstd_register_mathlib(v);
+	sqstd_register_stringlib(v);
+	sqext_register_base64(v);
+	sqext_register_Sq_Fpdf(v);
+	sqext_register_SQLite3(v);
+	sqext_register_sqfs(v);
+	sqext_register_mix(v);
+	sqext_register_sq_socket(v);
+
+    sq_pushstring(v,sq_http_request_TAG, -1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)sq_http_request_TAG);
+    sq_insert_reg_funcs(v, mg_http_request_methods);
+    sq_pushstring(v, _SC("info"), -1);
+    sq_newtable(v);
+    sq_newslot(v,-3,SQFalse);
+    sq_newslot(v,-3,SQFalse);
+
+    sq_insert_reg_funcs(v, sq_mg_methods);
+
+    sq_pushliteral(v, "APP_ROOT_FOLDER");
+    sq_pushstring(v, mg_get_option(ctx, "document_root"), -1);
+    sq_newslot(v, -3, SQFalse);
+
+    sq_poptop(v); //remove roottable
+
+    return v;
+}
+
+SQInteger blob_read(SQUserPointer file,SQUserPointer p,SQInteger size);
+SQInteger loadstring(HSQUIRRELVM v, const char * bcode, SQInteger bcode_size)
+{
+    SQBlob b(0, bcode_size);
+    b.Write(bcode, bcode_size);
+    b.Seek(0, SQ_SEEK_SET);
+    SQInteger rc = sq_readclosure(v, blob_read, &b);
+	return rc < 0 ? rc : 1;
+}
+
+// dispatches a callback to a Lua function if one is registered
+static void *
+user_callback_proxy(enum mg_event event,
+                    struct mg_connection *conn,
+                    const struct mg_request_info *ri)
+{
+    HSQUIRRELVM v;
+    int e;
+
+    switch(event){
+        case MG_NEW_MASTER_PLUGIN: {
+            SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) conn;
+            SQ_MG_Callback *cb = sq_mg_ctx->master_plugin;
+            v = my_new_squirrel((struct mg_context *)ri);
+            if(!v) return 0;
+
+            if(cb){
+                if (loadstring(v, cb->buf, cb->size)  == 1) {
+                    sq_pushroottable(v);
+                    if(sq_call(v, 1, SQFalse, SQTrue) != SQ_OK){
+                        sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                    }
+                    sq_poptop(v); //remove function from stack
+                }
+            }
+            return v;
+        }
+        break;
+
+        case MG_FREE_MASTER_PLUGIN:
+            v = (HSQUIRRELVM)conn;
+            if(v) {
+                SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) ri;
+                SQ_MG_Callback *cb = sq_mg_ctx->master_plugin_exit;
+                if(cb){
+                    if (loadstring(v, cb->buf, cb->size) == 1) {
+                        sq_pushroottable(v);
+                        if(sq_call(v, 1, SQFalse, SQFalse) != SQ_OK){
+                            sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                        }
+                        sq_poptop(v); //remove function from stack
+                    }
+                    else sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                }
+                sq_close(v);
+            }
+            return 0;
+        break;
+
+        case MG_NEW_PLUGIN:{
+            SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) mg_get_user_data(conn);
+            if(!sq_mg_ctx) return 0;
+            SQ_MG_Callback *cb = sq_mg_ctx->user_callback;
+            if (cb) {
+                v = my_new_squirrel((struct mg_context *)ri);
+                if(!v) return 0;
+                SQInteger top = sq_gettop(v);
+                SQ_MG_Callback *cb_setup = sq_mg_ctx->user_callback_setup;
+                if(cb_setup){
+                    if (loadstring(v, cb_setup->buf, cb_setup->size) == 1) {
+                        sq_pushroottable(v);
+                        if(sq_call(v, 1, SQFalse, SQFalse) != SQ_OK){
+                            sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                        }
+                        sq_poptop(v); //remove function from stack
+                    }
+                    else sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                }
+                sq_pushroottable(v);
+                sq_pushstring(v, sq_mg_user_callback, -1);
+                if (loadstring(v, cb->buf, cb->size) == 1) {
+                    sq_newslot(v, -3, SQFalse);
+                }
+                else sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                sq_settop(v, top); //remove everithing left on stack while working here
+                return v;
+            }
+        }
+        return 0;
+
+        case MG_FREE_PLUGIN:
+            v = (HSQUIRRELVM)mg_get_plugin(conn);
+            if(v){
+                SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) ri;
+                if(sq_mg_ctx){
+                    SQ_MG_Callback *cb = sq_mg_ctx->user_callback_exit;
+                    if(cb){
+                        if (loadstring(v, cb->buf, cb->size) == 1) {
+                            sq_pushroottable(v);
+                            if(sq_call(v, 1, SQFalse, SQFalse) != SQ_OK){
+                                sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                            }
+                            sq_poptop(v); //remove function from stack
+                        }
+                        else sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
+                    }
+                }
+                sq_close(v);
+            }
+        return NULL;
+
+        case MG_INIT_SSL:
+#ifdef USE_AXTLS
+            //lua_pushstring(L, "MG_INIT_SSL");
+            *((void**)conn) = SSL_CTX_new(0);
+            return 0;
+#endif
+        case MG_NEW_REQUEST:
+        case MG_HTTP_ERROR:
+        case MG_EVENT_LOG:{
+            v = (HSQUIRRELVM) mg_get_plugin(conn);
+
+            if (v) {
+                SQInteger saved_top = sq_gettop(v);
+                //SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) mg_get_user_data(conn);
+                sq_pushstring(v, sq_mg_user_callback, -1);
+                if(sq_getonroottable(v) != SQ_OK) {
+                    write_error_message(conn, "failed to find mg_user_callback", -1);
+                    return NULL;
+                }
+                sq_pushroottable(v);
+
+#define CASE(n) case n: sq_pushstring(v, #n, -1);break
+                switch(event){
+                    CASE(MG_INIT_SSL);
+                    CASE(MG_HTTP_ERROR);
+                    CASE(MG_EVENT_LOG);
+                    CASE(MG_NEW_REQUEST);
+                    default:
+                        sq_pushnull(v);
+                }
+
+                sq_pushstring(v, sq_http_request_TAG, -1);
+                if(sq_getonroottable(v) == SQ_OK){
+                    sq_pushroottable(v);
+                    if(sq_call(v, 1, SQTrue, SQFalse) == SQ_OK){
+                        sq_remove(v, -2); //remove class
+                        sq_setinstanceup(v, -1, conn);
+                    }
+                }
+                push_request(v, ri);
+
+                if(sq_call(v, 3, SQTrue, SQTrue) != SQ_OK) {
+                    write_error_message(conn, sq_getlasterror_str(v), -1);
+                    e = 0;
+                } else {
+                    SQBool bval;
+                    if(sq_getbool(v, -1, &bval) == SQ_OK) e = bval == SQTrue ? 1 : 0;
+                    else e = 0;
+                }
+
+                sq_settop(v, saved_top);
+                return (void *) e;
+            }
+        }
+
+        default:
+            return NULL;
+    }
+
+    return NULL;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_mongoose(HSQUIRRELVM v)
+    {
+        sq_insert_reg_funcs(v, sq_mg_methods);
+        sq_pushstring(v,sq_mongoose_TAG, -1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(void*)sq_mongoose_TAG);
+        sq_insert_reg_funcs(v, sq_mongoose_methods);
+        sq_newslot(v,-3,SQTrue);
+        return 1;
+    }
+
+#ifdef __cplusplus
+}
+#endif
+

+ 175 - 0
ext/sq_zlib.cpp

@@ -0,0 +1,175 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <zlib.h>
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+SQ_OPT_STRING_STRLEN();
+
+#define LZ_BUFFER_SIZE 8192
+
+static int sq_check_result(HSQUIRRELVM v, int result, const z_stream* stream) {
+    /* Both of these are "normal" return codes: */
+    if ( result == Z_OK || result == Z_STREAM_END ) return SQ_OK;
+    switch ( result ) {
+    case Z_NEED_DICT:
+        return sq_throwerror(v, _SC("RequiresDictionary: input stream requires a dictionary to be deflated (%s)"),
+                        stream->msg);
+        break;
+    case Z_STREAM_ERROR:
+        return sq_throwerror(v, _SC("InternalError: inconsistent internal zlib stream (%s)"),
+                        stream->msg);
+        break;
+    case Z_DATA_ERROR:
+        return sq_throwerror(v, _SC("InvalidInput: input string does not conform to zlib format or checksum"));
+        break;
+    case Z_MEM_ERROR:
+        return sq_throwerror(v, _SC("OutOfMemory: not enough memory (%s)"), stream->msg);
+        break;
+    case Z_BUF_ERROR:
+        return sq_throwerror(v, _SC("InternalError: no progress possible (%s)"), stream->msg);
+        break;
+    case Z_VERSION_ERROR:
+        return sq_throwerror(v, _SC("IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s)"),
+                        ZLIB_VERSION,  zlibVersion(), stream->msg);
+        break;
+    default:
+        return sq_throwerror(v, _SC("ZLibError: unknown code %d (%s)"), result, stream->msg);
+    }
+    return SQ_OK;
+}
+
+static SQRESULT sq_zlib_deflate(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 2, data);
+    SQ_OPT_INTEGER(v, 3, level, Z_DEFAULT_COMPRESSION);
+    /*  Allocate the stream: */
+    z_stream stream;
+
+    stream.zalloc = Z_NULL;
+    stream.zfree  = Z_NULL;
+    if(sq_check_result(v, deflateInit(&stream, level), &stream) != SQ_OK) return SQ_ERROR;
+
+    SQBlob b(LZ_BUFFER_SIZE);
+
+    /*  Do the actual deflate'ing: */
+    stream.next_in = (unsigned char*)data;
+    stream.avail_in = data_size;
+    if ( ! stream.avail_in ) {
+        /*  Passed empty string, make it a noop instead of erroring out. */
+        sq_pushliteral(v, "");
+        return 1;
+    }
+
+    int nchunks = 0;
+    do {
+        stream.next_out  = ((unsigned char*)b.GetBuf()) + (LZ_BUFFER_SIZE * nchunks++);
+        stream.avail_out = LZ_BUFFER_SIZE;
+        int result = deflate(&stream, Z_FINISH);
+        if (result == Z_STREAM_END )
+            break;
+        if (result != Z_OK)
+        {
+            sq_check_result(v, result, &stream);
+            deflateEnd(&stream);
+            return SQ_ERROR;
+        }
+        b.GrowBufOf(LZ_BUFFER_SIZE);
+    } while ( stream.avail_out == 0 );
+
+    SQInteger total_out = stream.total_out;
+    /*  Close the stream: */
+    if(sq_check_result(v, deflateEnd(&stream), &stream) == SQ_ERROR) return SQ_ERROR;
+
+    /*  Need to do this before we alter the stack: */
+    sq_pushstring(v, (const SQChar*)b.GetBuf(), total_out);
+
+    return 1;
+}
+
+static SQRESULT sq_zlib_inflate(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SQ_GET_STRING(v, 2, data);
+    /*  By default, we will do gzip header detection w/ max window size */
+    SQ_OPT_INTEGER(v, 3, window_size, MAX_WBITS + 32);
+    /*  Allocate the stream: */
+    z_stream stream;
+
+    stream.zalloc = Z_NULL;
+    stream.zfree  = Z_NULL;
+    if(sq_check_result(v, inflateInit2(&stream, window_size), &stream) != SQ_OK) return SQ_ERROR;
+
+    SQBlob b(LZ_BUFFER_SIZE);
+
+    /*  Do the actual deflate'ing: */
+    stream.next_in = (unsigned char*)data;
+    stream.avail_in = data_size;
+    if ( ! stream.avail_in ) {
+        /*  Passed empty string, make it a noop instead of erroring out. */
+        sq_pushliteral(v, "");
+        return 1;
+    }
+
+    int nchunks = 0;
+    do {
+        stream.next_out  = ((unsigned char*)b.GetBuf()) + (LZ_BUFFER_SIZE * nchunks++);
+        stream.avail_out = LZ_BUFFER_SIZE;
+        int result = inflate(&stream, Z_FINISH);
+        if ( Z_BUF_ERROR != result ) {
+            /* Ignore Z_BUF_ERROR since that just indicates that we
+             * need a larger buffer in order to proceed.  Thanks to
+             * Tobias Markmann for finding this bug!
+             */
+            if(sq_check_result(v, result, &stream) == SQ_OK) break;
+            else {
+                inflateEnd(&stream);
+                return SQ_ERROR;
+            }
+        }
+        b.GrowBufOf(LZ_BUFFER_SIZE);
+    } while ( stream.avail_out == 0 );
+
+    SQInteger total_out = stream.total_out;
+    /*  Close the stream: */
+    if(sq_check_result(v, inflateEnd(&stream), &stream) == SQ_ERROR) return SQ_ERROR;
+
+    /*  Need to do this before we alter the stack: */
+    sq_pushstring(v, (const SQChar*)b.GetBuf(), total_out);
+
+    return 1;
+}
+
+static int sq_zlib_version(HSQUIRRELVM v)
+{
+    sq_pushstring(v, zlibVersion(), -1);
+    return 1;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define INT_CONST(v,num) 	sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue);
+
+
+    SQRESULT sqext_register_sq_zlib(HSQUIRRELVM v)
+    {
+        sq_pushliteral(v,_SC("zlib"));
+        sq_newtable(v);
+        INT_CONST(v, Z_DEFAULT_COMPRESSION);
+        INT_CONST(v, Z_BEST_SPEED);
+        INT_CONST(v, Z_BEST_COMPRESSION);
+
+        sq_insertfunc(v, _SC("version"), sq_zlib_version, 1, _SC("."), SQTrue);
+        sq_insertfunc(v, _SC("deflate"), sq_zlib_deflate, -2, _SC(".si"), SQTrue);
+        sq_insertfunc(v, _SC("inflate"), sq_zlib_inflate, -2, _SC(".si"), SQTrue);
+
+        sq_newslot(v,-3,SQTrue); //push zlib table
+        return 0;
+    }
+
+#ifdef __cplusplus
+}
+#endif