// file.cpp : Defines the entry point for the DLL application.
 
 
 
//
 
 
 
 
 
 
 
#include "stdafx.h"
 
 
 
#include "file.h"
 
 
 
 
 
 
 
#include <stdio.h>
 
 
 
#include <stdlib.h>
 
 
 
#include <sys/types.h>
 
 
 
#include <sys/stat.h>
 
 
 
#include <io.h>
 
 
 
 
 
 
 
#include "sqlite3ext.h"
 
 
 
SQLITE_EXTENSION_INIT1
 
 
 
 
 
 
 
int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){
 
 
 
  int i, j, e, m;
 
 
 
  int cnt[256];
 
 
 
  if( n<=0 ){
 
 
 
    out[0] = 'x';
 
 
 
    out[1] = 0;
 
 
 
    return 1;
 
 
 
  }
 
 
 
  memset(cnt, 0, sizeof(cnt));
 
 
 
  for(i=n-1; i>=0; i--){ cnt[in[i]]++; }
 
 
 
  m = n;
 
 
 
  for(i=1; i<256; i++){
 
 
 
    int sum;
 
 
 
    if( i=='\'' ) continue;
 
 
 
    sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff];
 
 
 
    if( sum<m ){
 
 
 
      m = sum;
 
 
 
      e = i;
 
 
 
      if( m==0 ) break;
 
 
 
    }
 
 
 
  }
 
 
 
  out[0] = e;
 
 
 
  j = 1;
 
 
 
  for(i=0; i<n; i++){
 
 
 
    int c = (in[i] - e)&0xff;
 
 
 
    if( c==0 ){
 
 
 
      out[j++] = 1;
 
 
 
      out[j++] = 1;
 
 
 
    }else if( c==1 ){
 
 
 
      out[j++] = 1;
 
 
 
      out[j++] = 2;
 
 
 
    }else if( c=='\'' ){
 
 
 
      out[j++] = 1;
 
 
 
      out[j++] = 3;
 
 
 
    }else{
 
 
 
      out[j++] = c;
 
 
 
    }
 
 
 
  }
 
 
 
  out[j] = 0;
 
 
 
  return j;
 
 
 
}
 
 
 
 
 
 
 
BOOL APIENTRY DllMain( HANDLE hModule, 
 
 
 
                       DWORD  ul_reason_for_call, 
 
 
 
                       LPVOID lpReserved
 
 
 
                     )
 
 
 
{
 
 
 
    switch (ul_reason_for_call)
 
 
 
    {
 
 
 
        case DLL_PROCESS_ATTACH:
 
 
 
        case DLL_THREAD_ATTACH:
 
 
 
        case DLL_THREAD_DETACH:
 
 
 
        case DLL_PROCESS_DETACH:
 
 
 
            break;
 
 
 
    }
 
 
 
    return TRUE;
 
 
 
}
 
 
 
 
 
 
 
 
 
 
 
/*
 
 
 
** The fileFunc() SQL function returns the encoded contents of a file
 
 
 
*/
 
 
 
static void fileFunc(
 
 
 
  sqlite3_context *context,
 
 
 
  int argc,
 
 
 
  sqlite3_value **argv
 
 
 
){
 
 
 
 
 
 
 
    if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){
 
 
 
    sqlite3_result_null(context);
 
 
 
    return;
 
 
 
  }
 
 
 
 
 
 
 
    const char *filename = (const char *)sqlite3_value_text(argv[0]);
 
 
 
  if( 0==filename ){
 
 
 
    filename="";
 
 
 
  }
 
 
 
 
 
 
 
    struct _stat sbuf;
 
 
 
    int res = _stat( filename, &sbuf );
 
 
 
    if (res!=0){
 
 
 
        sqlite3_result_error(context, "file not found", -1);
 
 
 
        return;
 
 
 
    }
 
 
 
    long size = sbuf.st_size;
 
 
 
 
 
 
 
    FILE * pFile;
 
 
 
  pFile = fopen (filename, "rb" );
 
 
 
    if (pFile){
 
 
 
 
 
 
 
        char *buf = (char*)sqlite3_malloc(size); // +1
 
 
 
        fread((void *)buf, sizeof( char ), size, pFile);
 
 
 
        fclose (pFile);
 
 
 
 
 
 
 
        char *out = (char*)sqlite3_malloc(2 +(257*size)/254);
 
 
 
        size = sqlite_encode_binary((const unsigned char *)buf, size, (unsigned char *)out);
 
 
 
        sqlite3_free(buf);
 
 
 
 
 
 
 
        sqlite3_result_text(context, out, -1, SQLITE_TRANSIENT);
 
 
 
        sqlite3_free(out);
 
 
 
 
 
 
 
    }else
 
 
 
        sqlite3_result_error(context, "file could not be opened", -1);
 
 
 
}
 
 
 
 
 
 
 
/* SQLite invokes this routine once when it loads the extension.
 
 
 
** Create new functions, collating sequences, and virtual table
 
 
 
** modules here.  This is usually the only exported symbol in
 
 
 
** the shared library.
 
 
 
*/
 
 
 
int sqlite3_extension_init(
 
 
 
  sqlite3 *db,
 
 
 
  char **pzErrMsg,
 
 
 
  const sqlite3_api_routines *pApi
 
 
 
){
 
 
 
  SQLITE_EXTENSION_INIT2(pApi)
 
 
 
  sqlite3_create_function(db, "FILE", 1, SQLITE_ANY, 0, fileFunc, 0, 0);
 
 
 
  return 0;
 
 
 
}