- #include <libpq-fe.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <stdlib.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/uio.h>
- #include <fcntl.h>
- #include "serv.h"
- /*
- à compiler avec :
- gcc -I`pg_config --includedir` -L`pg_config --libdir` -lpq base.c server.c
- *//
- int numero = 0;
- char *
- fichier (char * id, char * numero)
- {
- char * res;
- asprintf (&res, "%s/%s.%s", SPOOLPATH, id, numero);
- return res;
- }
- PGconn *
- connecter ()
- {
- return PQconnectdb (PQCONN);
- }
- void deconnecter (PGconn* c)
- {
- PQfinish (c);
- free (c);
- }
- PGresult *
- executer (char* requete)
- {
- PGconn* c = connecter ();
- PGresult * res = PQexec (c, requete);
- deconnecter (c);
- return res;
- }
- char *
- escape (char* ch)
- {
- int n = strlen (ch);
- char *res = malloc (sizeof (char[2*n + 1]));
- PQescapeString (res, ch, n);
- return res;
- }
- char *
- lire_fichier (char * fichier, int * taille)
- {
- char *buff = malloc (1);
- FILE *fich = fopen (fichier, "r");
- int pos = 0;
- int lus = 0;
- while (!(feof (fich)))
- {
- realloc (buff, pos + 1024);
- lus = fread (&buff[pos], 1, 1023, fich);
- pos += lus;
- }
- *taille = pos;
- buff[pos] = 0;
- fclose (fich);
- return buff;
- }
- char *
- lire_message_par_id (char* id, int * taille)
- {
- char *requete;
- asprintf (&requete, \
- "select numero_fichier from messages where id = '%s';", \
- id);
- printf ("%s\n", requete);
- PGresult * res = executer (requete);
- free (requete);
- if (0 == PQntuples (res))
- return NULL;
- char * fich = fichier (id, PQgetvalue(res, 0, 0));
- char * resultat = lire_fichier (fich, taille);
- free (fich);
- return resultat;
- }
- char *
- message_id (char * conti, char * numero)
- {
- char *requete;
- char *resultat;
- asprintf (&requete, \
- "select message from messages_contis where conti = '%s' and numero = %s;", \
- conti, numero);
- printf ("%s\n", requete);
- PGresult * res = executer (requete);
- free (requete);
- if (0 != PQntuples (res))
- resultat = PQgetvalue (res, 0, 0);
- return resultat;
- }
- char *
- lire_conti (char * conti)
- {
- char *requete;
- asprintf (&requete, \
- "select numero,message from messages_contis where conti = '%s' order by numero;", \
- conti);
- printf ("%s\n", requete);
- PGresult * res = executer (requete);
- free (requete);
- int n = PQntuples (res);
- if (0 == n)
- return NULL;
- char * ret = malloc (1);
- *ret = 0;
- char * ret2;
- int i;
- for (i = 0; i < n; i++)
- {
- asprintf (&ret2, "%s%s:%s\n", \
- ret, PQgetvalue (res, i, 0), PQgetvalue (res, i, 1));
- free (ret);
- ret = ret2;
- }
- return ret;
- }
- char *
- lister_contis ()
- {
- PGresult * res = executer ("select nom from contis;");
- int n = PQntuples (res);
- if (0 == n)
- return NULL;
- char * ret = malloc (1);
- ret[0] = 0;
- char * ret2;
- int i;
- for (i = 0; i < n; i++)
- {
- asprintf (&ret2, "%s%s\n", ret, PQgetvalue (res, i, 0));
- free (ret);
- ret = ret2;
- }
- return ret;
- }
- char *
- creer_id (time_t date)
- {
- char *id;
- asprintf (&id, "%.8x%.8x", date, random ());
- return id;
- }
- void
- creer_message (struct msg * msg)
- {
- int i;
- /* génération du message id */ */
- srandom (msg->date);
- char * id = creer_id (msg->date);
- printf ("Création du message %s\n", id);
- char* sender = msg->sender;
- char* from = escape (msg->from);
- char* subject = escape (msg->subject);
- char * fichier_corps = fichier (id, "0");
- char * date = ctime (&(msg->date));
- date[24] = 0;
- char * req1 = malloc (1);
- req1[0] = 0;
- char * req15;
- char * req9;
- char * body1 = malloc (13);
- strcpy (body1, "REFERENCES: ");
- char * body15;
- PGresult * resref;
- int nbref_eff = 0;
- if (msg->nrefs > 0)
- {
- for (i = 0; i < msg->nrefs; i++)
- {
- asprintf (&req9, "select * from messages where id = '%s';", \
- msg->refs[i]);
- resref = executer (req9);
- free (req9);
- if (0 < PQntuples(resref))
- {
- nbref_eff++;
- asprintf (&body15, "%s%s, ", body1, msg->refs[i]);
- free (body1);
- body1 = body15;
- asprintf (&req15, \
- "%s insert into refs(de, a) values('%s','%s') ;", \
- req1, id, msg->refs[i]);
- free (req1);
- req1 = req15;
- }
- else
- {
- printf("Référence à un message inexistant : '%s'\n", \
- msg->refs[i]);
- }
- }
- if (nbref_eff != 0)
- body1[strlen (body1) - 2] = 0;
- char * pere = msg->refs[msg->nrefs - 1];
- asprintf (&req15, \
- "%s %s values ('%s', '%s', '%s', '%s', '%s', '%s'); %s (%s '%s') || '%s, ' %s '%s' ; %s;", \
- req1, \
- "insert into messages(id, date, sender, \"from\", subject, pere)", \
- id, date, sender, from, subject, pere, \
- "update messages set fils = ", \
- "select fils from messages where id = ", pere, \
- id, \
- "where id = ", pere, \
- "lock contis in row exclusive mode");
- free (req1);
- free (pere);
- req1 = req15;
- } else {
- asprintf (&req1, \
- "%s values ('%s', '%s', '%s', '%s', '%s'); %s;", \
- "insert into messages(id, date, sender, \"from\", subject) ", \
- id, date, sender, from, subject, \
- "lock contis in row exclusive mode");
- };
- PGresult * resconti;
- int nb_effectif = 0;
- char * body2 = malloc (13);
- strcpy (body2, "NEWSGROUPS: ");
- char * body25;
- for (i = 0; i < msg->nngrp ; i++)
- {
- char * conti = msg->newsgrps[i];
- asprintf (&req9, \
- "select lecture_seule from contis where nom = '%s';", \
- conti);
- resconti = executer (req9);
- free (req9);
- if (0 < PQntuples (resconti) && \
- 0 != strcmp ("t", PQgetvalue (resconti,0,0)))
- {
- nb_effectif++;
- asprintf (&body25, " , body2, conti);
- free (body2);
- body2 = body25;
- asprintf (&req15, \
- " "%s %s ('%s', '%s'%s'%s '%s')); %s %s '%s';" , \
- req1, \
- "insert into messages_contis (message, conti, numero) values", \
- id, conti, \
- "select prochain_numero from contis where nom = ", conti, \
- "update contis set prochain_numero = 1 + prochain_numero", \
- "where nom = ", conti);
- free (req1);
- req1 = req15;
- printf ("%s\n", req1);
- }
- else
- {
- printf ("Le conti '%s' n'existe pas ou est en lecture seule.\n", \
- conti);
- }
- }
- if (nb_effectif != 0)
- {/* effacer la dernière virgule */rgule */
- body2[strlen (body2) - 2] = 0;
- /* génération du corps complet */complet */
- char * body;
- asprintf (&body, "%s\nFROM: %s\nSENDER: %s\nSUBJECT: %s\n%s\n\n%s", \
- body2, msg->from, msg->sender, msg->subject, body1, msg->body);
- free (body1);
- free (body2);
- free (from);
- free (sender);
- free (subject);
- if (nb_effectif != 0)
- /* écriture du fichier */ fichier */
- FILE * fich = fopen (fichier_corps, "w");
- fprintf (fich, "%s", body);
- free (body);
- fclose (fich);
- printf ("Le fichier '%s' a été écrit.\n", fichier_corps);
- free (fichier_corps);
- printf ("La requête suivante va être exécutée :\n%s\n", req1);
- executer (req1);
- } else {
- printf ("Création annulée, pas de newsgroup.\n");
- }
- free (req1);
- }
- char **
- nouveau_t ()
- {
- char ** t = malloc (LMXSIZ * sizeof (char*));
- int i;
- for (i = 0; i < LMXSIZ; i++)
- {
- t[i] = malloc (LMXSIZ);
- };
- return t;
- }
- void
- maj_refs (PGconn * conn, char * id, char * anc_id1, char * nouv_id1)
- {
- int numfich = 0;
- char * req;
- asprintf (&req, "select numero_fichier from messages where id = '%s'", id);
- PGresult * res = PQexec (conn, req);
- free (req);
- sscanf (PQgetvalue(res, 0, 0), "%d", &numfich);
- numfich++;
- char * snumfich;
- asprintf (&snumfich, "%d", numfich);
- char * fichier_interm = fichier (id, snumfich);
- free (snumfich);
- char * snumfichp;
- asprintf (&snumfichp, "%d", numfich - 1);
- char * fichier_avant = fichier (id, snumfichp);
- free (snumfichp);
- FILE * f1 = fopen (fichier_avant, "r");
- FILE * f2 = fopen (fichier_interm, "w");
- free (fichier_avant);
- free (fichier_interm);
- char * ligne = malloc (LMXSIZ);
- int ligne_blanche = 0;
- char ** t;
- int i, n;
- char * refer = malloc (13);
- strcpy (refer, "REFERENCES: ");
- char * refer2;
- char * tampon;
- while (!(feof (f1)))
- {
- if (tampon != NULL)
- fputs (tampon, f2);
- fgets(ligne, LMXSIZ, f1 );
- if (ligne_blanche == 0 && \
- (strcmp (ligne, "\n") == 0 || strcmp (ligne, "") == 0))
- ligne_blanche = 1;
- if (ligne_blanche == 0 && \
- strcasecmp (ligne, "REFERENCES: ") > 0 && \
- strcmp (ligne, "REFERENCES:!") < 0)
- {
- t = nouveau_t ();
- n = parse (&ligne[12], t, 0, 0);
- for (i = 0; i < n; i++)
- {
- if (strcmp (anc_id1, t[i]) == 0)
- {
- asprintf (&refer2, "%s%s, ", refer, nouv_id1);
- refer = refer2;
- } else {
- asprintf (&refer2, "%s%s, ", refer, t[i]);
- };
- free (refer);
- refer = refer2;
- free (t[i]);
- }
- free (tampon);
- refer[strlen(refer) - 2] = 0;
- asprintf (&tampon, "%s\n", refer);
- free (refer);
- free (t);
- }
- else
- {
- free (tampon);
- asprintf (&tampon, "%s", ligne);
- }
- };
- free (tampon);
- fclose (f1);
- fclose (f2);
- asprintf (&req, \
- "%s where id = '%s'", \
- "update messages set numero_fichier = 1 + numero_fichier", \
- id);
- PQexec (conn, req);
- free (req);
- }
- char *
- deplacer (PGconn * conn, char * id, time_t date, char * cdate, \
- char * source, char * cible)
- {
- if (0 == strcmp (source, cible))
- return id;
- printf ("Début du déplacement de %s\n", id);
- char * req;
- PGresult * res;
- asprintf (&req, \
- "delete from messages_contis where message = '%s' and conti = '%s';", \
- id, source);
- PQexec (conn, req);
- free (req);
- int numfich = 0;
- asprintf (&req, "select numero_fichier from messages where id = '%s'", id);
- res = PQexec (conn, req);
- free (req);
- if (0 == PQntuples (res))
- return NULL;
- char * snumfichp = PQgetvalue (res, 0, 0);
- sscanf (snumfichp, "%d", &numfich);
- numfich++;
- char * snumfichs;
- asprintf (&snumfichs, "%d", numfich);
- printf ("%s\n", snumfichs);
- char * fichier_avant = fichier (id, snumfichp);
- char * fichier_interm = fichier (id, snumfichs);
- free (snumfichs);
- FILE * f1 = fopen (fichier_avant, "r");
- FILE * f2 = fopen (fichier_interm, "w");
- free (fichier_avant);
- char * ligne = malloc (LMXSIZ);
- int ligne_blanche = 0;
- char ** t;
- char * newsgrp = malloc (13);
- strcpy (newsgrp, "NEWSGROUPS: ");
- char * newsgrp2;
- int n = 0;
- int i;
- asprintf (&req, \
- "%s = '%s'; %s = '%s' and conti = '%s';", \
- "update messages set numero_fichier = 1+ numero_fichier where id", \
- id, \
- "select message from messages_contis where message", \
- id, cible);
- res = PQexec (conn, req);
- free (req);
- int dans_cible = (0 != PQntuples (res));
- char * tampon = NULL;
- while (!(feof (f1)))
- {
- if (tampon != NULL)
- fputs (tampon, f2);
- fgets (ligne, LMXSIZ, f1);
- if (ligne_blanche == 0 && \
- (strcmp (ligne, "\n") == 0 || strcmp (ligne, "") == 0))
- ligne_blanche = 1;
- if (ligne_blanche == 0 && \
- strcasecmp (ligne, "NEWSGROUPS: ") > 0 && \
- strcasecmp (ligne, "NEWSGROUPS:!") < 0)
- {
- t = nouveau_t ();
- n = parse (&ligne[12], t, 0, 0);
- for (i = 0; i < n - 1; i++)
- {
- if (strcmp (source, t[i]) == 0)
- {
- if (!dans_cible)
- {
- asprintf (&newsgrp2, "%s%s, ", newsgrp, cible);
- free (newsgrp);
- newsgrp = newsgrp2;
- }
- } else {
- asprintf (&newsgrp2, "%s%s, ", newsgrp, t[i]);
- free (newsgrp);
- newsgrp = newsgrp2;
- };
- free (t[i]);
- }
- free (t);
- free (tampon);
- newsgrp[strlen (newsgrp - 2)] = 0;
- asprintf (&tampon, "%s\n", newsgrp);
- }
- else
- {
- free (tampon);
- asprintf (&tampon, "%s", ligne);
- }
- };
- free (tampon);
- fclose (f1);
- fclose (f2);
- if (dans_cible) {
- free (fichier_interm);
- return id;
- };
- char * nouv_id = creer_id (date);
- char * nouv_fichier = fichier (nouv_id, "0");
- rename (fichier_interm, nouv_fichier);
- free (fichier_interm);
- free (nouv_fichier);
- asprintf (&req, " select de from refs where a = '%s' ;", id);
- res = PQexec (conn, req);
- free (req);
- n = PQntuples (res);
- for (i = 0; i < n ; i++)
- {
- maj_refs (conn, PQgetvalue (res, i, 0), id,/* màj du champ fils du père du message à déplacer */du message à déplacer */
- asprintf (&req, "select pere from messages where id = '%s'; ", id);
- res = PQexec (conn, req);
- free (req);
- char * pere = PQgetvalue (res, 0, 0);
- char * req2;
- if (0 == strcmp (pere, ""))
- {
- printf ("Le message '%s' n'a pas de père.\n",id);
- req2 = malloc (1);
- req2[0] = 0;
- }
- else
- {
- asprintf (&req, "select fils from messages where id = '%s'; ", pere);
- res = PQexec (conn, req);
- free (req);
- t = nouveau_t ();
- n = parse (PQgetvalue (res, 0, 0) , t, 0, 0);
- char * fils = malloc (1);
- fils[0] = 0;
- char * fils2;
- for (i = 0; i < n - 1 ; i++)
- {
- if (strcmp (t[i], id) == 0)
- asprintf (&fils2, "%s%s, ", fils, nouv_id);
- else
- asprintf (&fils2, "%s%s, ", fils, t[i]);
- free (fils);
- fils = fils2;
- };
- asprintf (&req2, "update messages set fils = '%s' where id = '%s';", \
- fils, pere);
- };
- asprintf (&req, "%s %s '%s' %s '%s'; %s '%s' %s '%s'; %s '%s' %s '%s'; %s '%s', %s ', (%s ''%s'; %s ('%s', '%s', (%s '%s')); %s '%s';", \
- req2, \
- ", nouv_id, "ges set pere =", nouv_id, "where pere =", id, \
- "update refs set a =", nouv_id, "where a =", id, \
- "update refs set de =", nouv_id, "where de =", id, \
- "update messages set id =", nouv_id, \
- ", cdate, \
- " =", cdate, \
- "where id =", id, \
- "insert into messages_contis(message,conti,numero) values", \
- nouv_id, cible, \
- "select prochain_numero from contis where nom =", cible, \
- "update contis set prochain_numero = 1 + prochain_numero where nom =", \
- cible);
- free (req2);
- printf ("\nLe message '%s' du conti ' du conti ' le message '%s' du conti '%s'\n%s\n", \
- id, source, nouv_id, cible, req);
- PQexec (conn, req);
- free (req);
- return nouv_id;
- }
- void
- deplacer_message (char *utilisateur, char * id, char * source, char * cible)
- {
- time_t date = time (NULL);
- char * cdate = ctime (&date);
- cdate[24] = 0;
- PGconn * conn = connecter ();
- char * req;
- asprintf (&req, "select * from droits where conti = '%s' and moderateur = '%s'", \
- source, utilisateur);
- PGresult * res = PQexec (conn, req);
- free (req);
- if (PQntuples(res) == 0) {
- printf ("L'utilisateur '%s' n'a pas le droit de déplacer des messages depuis le conti '%s'.\n", \
- utilisateur, source);
- return;
- };
- asprintf (&req, "%s '%s' and (contis.lecture_seule = 'f' or (%s '%s'))", \
- "select * from droits,contis where contis.nom =", cible, \
- "droits.conti = contis.nom and droits.ecrire = 't' and droits.moderateur =", \
- utilisateur);
- res = PQexec (conn, req);
- free (req);
- if (PQntuples(res) == 0)
- {
- printf("L'utilisateur '%s' n'a pas le droit de déplacer des messages vers le conti '%s'.\n", \
- utilisateur, cible);
- return;
- };
- PQexec (conn, \
- "begin; lock refs,messages,messages_contis in exclusive mode; lock contis in row exclusive mode;");
- srandom (date);
- free (deplacer (conn, id, date, cdate, source, cible));
- PQexec (conn, "commit;");
- deconnecter (conn);
- }
- void
- deplacer_fils_rec (PGconn * conn, char * rootid, time_t date, char * cdate, \
- char * source, char * cible)
- {
- char * nouv_rootid = deplacer (conn, rootid, date, cdate, source, cible);
- if (NULL == nouv_rootid)
- return;
- char * req;
- asprintf (&req, \
- "select messages.id from messages,messages_contis where messages.id = messages_contis.message and messages_contis.conti = '%s' and messages.pere = '%s';", \
- source, nouv_rootid);
- PGresult * res = PQexec (conn, req);
- free (req);
- int n = PQntuples (res);
- int i;
- for (i = 0; i < n; i++)
- {
- deplacer_fils_rec (conn, PQgetvalue (res, i, 0), date, cdate, \
- source, cible);
- }
- free (nouv_rootid);
- }
- void
- deplacer_thread (char * utilisateur,
- char * rootid, char * source, char * cible)
- {
- time_t date = time (NULL);
- char * cdate = ctime (&date);
- cdate[24] = 0;
- PGconn * conn = connecter ();
- char * req;
- asprintf(&req, \
- "select * from droits where conti = '%s' and moderateur = '%s'", \
- source, utilisateur);
- PGresult * res = PQexec (conn, req);
- free (req);
- if (PQntuples(res) == 0)
- {
- printf("L'utilisateur '%s' n'a pas le droit de déplacer des messages depuis le conti '%s'.\n", \
- utilisateur, source);
- return;
- };
- asprintf (&req, "select * from droits,contis where contis.nom = '%s'f'nd (contis.lecture_seule = 'f' or (droits.conti = contis.nom and droits.moderateur = '%s' and droits.ecrire = 't') )", \
- cible, utilisateur);
- res = PQexec(conn, req);
- free(req);
- if( PQntuples(res) == 0)
- {
- printf ("L'utilisateur '%s' n'a pas le droit de déplacer des messages vers le conti '%s'.\n", \
- utilisateur, cible);
- return;
- };
- PQexec (conn, \
- "begin; lock refs,messages,messages_contis in exclusive mode; lock contis in row exclusive mode;");
- srandom (date);
- deplacer_fils_rec (conn, rootid, date, cdate, source, cible);
- PQexec (conn, "commi
Raw Paste