]> SAFE projects GIT repository - jmp/mailleur/commitdiff
Adding module unisql.c
authorJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 24 Jun 2025 22:45:56 +0000 (18:45 -0400)
committerJean-Marc Pigeon (Delson) <jmp@safe.ca>
Tue, 24 Jun 2025 22:45:56 +0000 (18:45 -0400)
lib/Makefile
lib/devsql.c
lib/devsql.h
lib/unimar.c
lib/unimar.h
lib/unipos.c
lib/unipos.h
lib/unisql.c [new file with mode: 0644]
lib/unisql.h [new file with mode: 0644]

index 97fc739bcb78efba1538d85bb632fc06d134bb22..dff637052b549ff7debfb4c30520ec4f1399e0aa 100644 (file)
@@ -24,7 +24,7 @@ OBJS=                                         \
          gesspf.o gestcp.o geseml.o            \
          devlog.o devsoc.o devsql.o            \
          unidns.o unieml.o unipar.o            \
-         uniprc.o unisig.o unitls.o            \
+         uniprc.o unisig.o unisql.o unitls.o   \
          subafn.o subrou.o 
 
 LIBS=                                          \
@@ -131,6 +131,9 @@ gesspf.h:                                   \
 devsoc.h:                                      \
           unitls.h
 
+devsql.h:                                      \
+          unisql.h
+
 uniprc.h:                                      \
           subrou.h
 
index eb07c7fbc5ca5c006f535096b5f42004c2897b2e..4ba5e0dbf7408307b518d085d55b5a84f6d75c9d 100644 (file)
@@ -5,6 +5,7 @@
 /*     to handle SQL request                           */
 /*                                                     */
 /********************************************************/
+#include        <ctype.h>
 #include        <stdlib.h>
 #include        <string.h>
 
@@ -112,7 +113,20 @@ while (proceed==true) {
         }
       break;
     case 3      :       //checking if the database is properly open
-      if (sql->db.psql==(POSPTR *)0) {
+      _Bool isok;
+
+      isok=false;
+      switch (sql->sqldb) {
+        case db_postgres:
+          isok=(sql->db.psql!=(POSPTR *)0);
+          break;
+        case db_maria   :
+          isok=(sql->db.msql!=(MARPTR *)0);
+          break;
+        default         :
+          break;
+        }
+      if (isok==false) {
         (void) rou_alert(0,"%s data-base not properly connected (config?)",OPEP);
         (void) free(sql);
         sql=(SQLTYP *)0;
@@ -163,7 +177,7 @@ while (proceed==true) {
           sql->db.psql=pos_closesql(sql->db.psql);
           break;
         case db_maria        :
-          sql->db.msql=mar_closesql(sql->db.psql);
+          sql->db.msql=mar_closesql(sql->db.msql);
           break;
         default                 :
           (void) rou_alert(0,"%s Unexpected type='%d' (bug?)",
@@ -184,3 +198,114 @@ while (proceed==true) {
 return (SQLPTR *)sql;
 #undef  OPEP
 }
+/*
+\f
+*/
+/********************************************************/
+/*                                                      */
+/*      Procedure to make sure a string to be use to    */
+/*      access database is clean.                       */
+/*      (no character to be misunderstood by database)  */
+/*                                                      */
+/********************************************************/
+PUBLIC char *sql_cleanstr(SQLPTR *sqlptr,char *str)
+
+{
+#define OPEP    "devsql.c:sql_cleanstr,"
+char *cleanstr;
+SQLTYP *sql;
+
+cleanstr=(char *)0;
+sql=(SQLTYP *)sqlptr;
+if (str!=(char *)0) {
+  (void) sql_checkencoding(str);
+  switch(sql->sqldb) {
+    case (db_postgres)  :
+      cleanstr=pos_cleanquote(str);
+      break;
+    case (db_maria)     :
+      cleanstr=mar_cleanquote(str);
+      break;
+    case (db_unknown)   :
+    default             :
+      (void) rou_alert(0,"%s Unknown SQL daemon (type='%d')",OPEP,sql->sqldb);
+      break;
+    }
+  }
+else
+  cleanstr=strdup("NULL");
+return cleanstr;
+
+#undef  OPEP
+}
+/*
+\f
+*/
+/********************************************************/
+/*                                                      */
+/*      Procedure to retreive information about user    */
+/*      known within database.                          */
+/*                                                      */
+/********************************************************/
+PUBLIC USRTYP *sql_getusr(SQLPTR *sqlptr,char *email)
+
+{
+#define OPEP    "devsql.c:sql_getuser,"
+
+USRTYP *usr;
+SQLTYP *sql;
+int phase;
+_Bool proceed;
+
+usr=(USRTYP *)0;
+sql=(SQLTYP *)sqlptr;
+phase=0;
+proceed=true;
+while (proceed==true) {
+  switch (phase) {
+    case 0      :       //checking SQL
+      if (sql==(SQLTYP *)0) {
+        (void) rou_alert(0,"%s SQL pointer is NUll (Bug?)",OPEP);
+        phase=999;
+        }
+      break;
+    case 1      :       //is email defined?
+      if ((email==(char *)0)||(strlen(email)==0)) {
+        (void) rou_alert(0,"%s Email <%s> is NUll or empty (Bug?)",OPEP,email);
+        phase=999;
+        }
+      break;
+    case 2      :       //check email structure
+      for (int i=0,l=strlen(email);i<l;i++) {
+        char car;
+      
+        car=email[i];
+        if (isalnum((int)car)!=0)
+          continue;
+        if (car=='@')
+          continue;
+        (void) rou_alert(0,"%s Email <%s> not accepted, '%c' not an email char",
+                            OPEP,email,car);
+        phase=999; 
+        }
+      break;
+    case 3      :       //opening specific database
+      switch (sql->sqldb) {
+        case db_postgres        :
+          break;
+        case db_maria        :
+          break;
+        default                 :
+          (void) rou_alert(0,"%s Unexpected type='%d' (bug?)",OPEP,sql->sqldb);
+          break;
+        }
+      break;
+    default     :
+      proceed=false;
+      break;
+    }
+  phase++;
+  }
+return usr;
+#undef  OPEP
+}
index 7507cf0bafb08881c78c8e71d1b646564a2099b3..d128216b61080a0580f13e344f02c6a0ca384eab 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef        DEVSQL
 #define DEVSQL
 
+#include        "unisql.h"
+
 //reference to a SQL pointer reference
 typedef void SQLPTR;
 
@@ -17,4 +19,11 @@ extern SQLPTR *sql_opensql();
 //procedure to close an previously opened SQL channel
 extern SQLPTR *sql_closesql(SQLPTR *sqlptr);
 
+//procedure to make sure a string with database
+//is clean
+extern char *sql_cleanstr(SQLPTR *sqlptr,char *str);
+
+//procedure to get information on exiting user
+extern USRTYP *sql_getusr(SQLPTR *sqlptr,char *email);
+
 #endif
index a3013c1ec0de3b3efc5f9e6a218a8136822ef87a..419721b74b49634091e9b4020d86cb4b7dbc0ba9 100644 (file)
@@ -8,6 +8,7 @@
 #include        <pwd.h>
 #include        <stdio.h>
 #include        <stdlib.h>
+#include        <string.h>
 #include        <unistd.h>
 #include        <mysql/mysql.h>
 #include        <sys/types.h>
@@ -91,5 +92,60 @@ return marptr;
 
 #undef  OPEP
 }
+/*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     Procedure to detect and 'clean' any single quote*/
+/*     within a string, this is mandatory for string   */
+/*      variable in the database.                       */
+/*     Single quote and double quote are translated to */
+/*      '\'' and '\"'                                   */
+/*                                                     */
+/********************************************************/
+char *mar_cleanquote(char *dstr)
+
+{
+char *cleanstr;
+int taille;
+char *ptr;
 
+taille=3;
+cleanstr=calloc(3,sizeof(char));
+cleanstr[0]='\'';
+if (dstr!=(char *)0) {
+  char *nptr;
+
+  ptr=dstr;
+  while (((nptr=strchr(ptr,'\''))!=(char *)0)||((nptr=strchr(ptr,'\"'))!=(char *)0)) {
+    char lit[3];
+    char *newclean;
+
+    (void) strcpy(lit,"\\'");
+    if (*nptr=='"')
+      lit[1]='"';
+    *nptr='\000';      /*to segment string     */
+    taille+=strlen(ptr)+2;
+    if ((newclean=(char *)realloc(cleanstr,taille))!=(char *)0) {
+      cleanstr=newclean;
+      (void) strcat(cleanstr,ptr);
+      (void) strcat(cleanstr,lit);
+      *nptr=lit[1];    /*to glue back string   */
+      ptr=nptr+1;
+      }
+    }
+  if (*ptr!='\000') {
+    char *newclean;
+
+    taille+=strlen(ptr);
+    if ((newclean=(char *)realloc(cleanstr,taille))!=(char *)0) {
+      cleanstr=newclean;
+      (void) strcat(cleanstr,ptr);
+      }
+    }
+  }
+(void) strcat(cleanstr,"'");
+return cleanstr;
+}
 
index b353cf01a7fda2b86afd59901ad0e699301e8d6f..efb8c22cca2c35723ef3c3ea19cb974e0cf03ea3 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef        UNIMAR
 #define UNIMAR
 
-
 //reference to a SQL pointer reference
 typedef void MARPTR;
 
@@ -18,4 +17,7 @@ extern MARPTR *mar_opensql(const char *host,const char *sqlport,const char *dbna
 //closing a postscript database
 extern MARPTR *mar_closesql(MARPTR *marptr);
 
+//Procedure to detect and 'clean' any single quote within a string
+extern char *mar_cleanquote(char *sequence);
+
 #endif
index df2c23ae348f9f0994057eeb678678575698ab47..bf59fa2e84e9f354701d2cd64057dcdb333765f7 100644 (file)
@@ -7,6 +7,8 @@
 /********************************************************/
 #include        <libpq-fe.h>
 #include        <stdio.h>
+#include        <stdlib.h>
+#include        <string.h>
 
 #include        "subrou.h"
 #include        "unipos.h"
@@ -90,5 +92,56 @@ return posptr;
 
 #undef  OPEP
 }
+/*
+\f
+*/
+/********************************************************/
+/*                                                     */
+/*     Procedure to detect and 'clean' any single quote*/
+/*     within a string, this is mandatory for string   */
+/*      variable in the database.                       */
+/*     Single quote "'" are doubled becoming "''"      */
+/*                                                     */
+/********************************************************/
+char *pos_cleanquote(register char *dstr)
 
+{
+char *cleanstr;
+int taille;
+
+cleanstr=strdup("E'");
+taille=strlen(cleanstr)+2;
+if (dstr!=(char *)0) {
+  int max;
+  int i,p;
+  char *newclean;
 
+  /*to double char ' in the string                     */
+  max=strlen((const char *)dstr);
+  taille+=max;
+  if ((newclean=(char *)realloc(cleanstr,taille))!=(char *)0) {
+    cleanstr=newclean;
+    p=strlen(cleanstr);
+    for (i=0;i<max;i++,p++,dstr++) {
+      switch (*dstr) {
+        case '\\'              :
+        case '\''              :
+          taille++;
+          if ((newclean=(char *)realloc(cleanstr,taille))!=(char *)0) {
+           cleanstr=newclean;
+            cleanstr=(char *)realloc(cleanstr,taille);
+            cleanstr[p]=*dstr;
+           }
+          p++;
+          break;
+        default                :
+         break;
+        }
+      cleanstr[p]=*dstr;
+      }
+    cleanstr[p]='\000';
+    }
+  }
+(void) strcat(cleanstr,"'");
+return cleanstr;
+}
index c4a8f2bb124e5c4b0702dd3414b757b2859d2d7c..1b6d440735779b5b70130754567dc73b8b8e441e 100644 (file)
@@ -17,4 +17,7 @@ extern POSPTR *pos_opensql(const char *host,const char *sqlport,const char *dbna
 //closing a postscript database
 extern POSPTR *pos_closesql(POSPTR *posptr);
 
+//Procedure to detect and 'clean' any single quote within a string
+extern char *pos_cleanquote(char *sequence);
+
 #endif
diff --git a/lib/unisql.c b/lib/unisql.c
new file mode 100644 (file)
index 0000000..c172200
--- /dev/null
@@ -0,0 +1,157 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/********************************************************/
+/*                                                     */
+/*     Module for low level SQL subroutine             */
+/*                                                     */
+/********************************************************/
+#include        <ctype.h>
+#include        <errno.h>
+#include        <iconv.h>
+#include        <stdbool.h>
+#include        <stdlib.h>
+#include        <string.h>
+
+#include       "subrou.h"
+#include       "unisql.h"
+
+#define DLANG   "UNICODE"
+
+/*
+\f
+*/
+/************************************************/
+/*                                             */
+/*     Procedure to convert an char sequence   */
+/*     from on char set to another.            */
+/*     if successful return a new pointer      */
+/*                                             */
+/************************************************/
+static char *cnvconvert(char *lfrom,char *lto,char *encoded)
+
+{
+#define        OPEP    "rousql.c:cnvconvert,"
+
+char *converted;
+char *marker;
+iconv_t hconv;
+size_t inbuflft;
+char *inbuf;
+size_t outbuflft;
+char *outbuf;
+int phase;
+int proceed;
+
+converted=(char *)0;
+marker=(char *)0;
+hconv=(iconv_t)0;
+inbuflft=(size_t)0;
+inbuf=(char *)0;
+outbuflft=(size_t)0;
+outbuf=(char *)0;
+phase=0;
+proceed=1;
+while (proceed==true) {
+  switch (phase) {
+    case 0     :       /*opening conv channel  */
+      if ((hconv=iconv_open(lto,lfrom))==(iconv_t)-1) {
+       (void) rou_alert(0,"%s Unexpected lang conversion request "
+                           "from=<%s> to=<%s> (errno=<%s>)",
+                          OPEP,lfrom,lto,strerror(errno));
+       phase=999;      /*trouble trouble       */
+       }
+      break;
+    case 1     :       /*doing convertion      */
+      inbuflft=strlen(encoded);
+      outbuflft=(inbuflft*4)+1;        /*spare room    */
+      inbuf=encoded;
+      marker=(char *)calloc(outbuflft,sizeof(char));
+      outbuf=marker;
+      if (iconv(hconv,&inbuf,&inbuflft,&outbuf,&outbuflft)==(size_t)(-1)) {
+       (void) rou_alert(2,"%s Unable to convert <%s> "
+                           "from=<%s> to=<%s> (errno=<%s>)",
+                          OPEP,encoded,lfrom,lto,strerror(errno));
+       (void) free(marker);
+       marker=(char *)0;
+       }
+      break;
+    case 2     :       /*doing convertion      */
+      if (iconv_close(hconv)<0) 
+       (void) rou_alert(0,"%s Unexpected close conversion error "
+                           "(errno=<%s>) (bug?)",OPEP,strerror(errno));
+      break;
+    default    :       /*SAFE Guard            */
+      converted=marker;
+      proceed=false;
+      break;
+    }
+  phase++;
+  }
+return converted;
+
+#undef  OPEP
+}
+/*
+\f
+*/
+/********************************************************/
+/*                                                      */
+/*      Procedure to free memory used by a user         */
+/*      definition.                                     */
+/*                                                      */
+/********************************************************/
+PUBLIC USRTYP *sql_freeusr(USRTYP *usr)
+
+{
+if (usr!=(USRTYP *)0) {
+  usr->email=rou_freestr(usr->email);
+  (void) free(usr);
+  usr=(USRTYP *)0;
+  }
+return usr;
+}
+/*
+\f
+*/
+/************************************************/
+/*                                             */
+/*     Routine to check if string is properly  */
+/*     coded, if it is not the case replace all*/
+/*     dubious charactere with plain ASCII     */
+/*                                             */
+/************************************************/
+PUBLIC void sql_checkencoding(char *strencoded)
+
+{
+char *ptr;
+int phase;
+int proceed;
+
+ptr=(char *)0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+  switch (phase) {
+    case 0     :       /*autoconvert string    */
+      if (((ptr=getenv("DB_LANG"))==(char *)0)||(strlen(ptr)==0))
+        ptr=DLANG;
+      if ((ptr=cnvconvert(ptr,ptr,strencoded))!=(char *)0) {
+        (void) free(ptr);
+        phase=999;     /*everything fine       */
+        }
+      break;
+    case 1     :       /*setting to plain ASCII*/
+      if (strencoded!=(char *)0) { /*alway     */
+       while (*strencoded!='\000') {
+         if (isascii(*strencoded)==0)
+           *strencoded='_';
+         strencoded++;
+         }
+       }
+      break;
+    default    :       /*SAFE Guard            */
+      proceed=false;
+      break;
+    }
+  phase++;
+  }
+}
diff --git a/lib/unisql.h b/lib/unisql.h
new file mode 100644 (file)
index 0000000..59c3f8d
--- /dev/null
@@ -0,0 +1,25 @@
+// vim: smarttab tabstop=8 shiftwidth=2 expandtab
+/************************************************/
+/*                                             */
+/*     Low level SQL subroutine declaration    */
+/*                                             */
+/************************************************/
+#ifndef        UNISQL
+#define UNISQL
+
+#include        <sys/types.h>
+
+//structure about user within the database
+typedef struct  {
+        char *email;    //user emails
+        u_long space;   //user space used;
+        u_long mxspace; //user maximun space
+        }USRTYP;
+
+//procedure to free space used by an USRTYP
+extern USRTYP *sql_freeusr(USRTYP *usr);
+
+//PRocedure to check if string is properly coded according DB_LANG
+extern void sql_checkencoding(char *strencoded);
+
+#endif