#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);
}
PGresult *
executer (char* requete)
{
PGconn* c = connecter ();
PGresult * res = PQexec (c, requete);
deconnecter (c);
return res;
}
char *
escape (char* ch)
{
char *res
= malloc (sizeof (char[2*n
+ 1]));
PQescapeString (res, ch, n);
return res;
}
char *
lire_fichier (char * fichier, int * taille)
{
FILE
*fich
= fopen (fichier
, "r"
);
int pos = 0;
int lus = 0;
{
lus
= fread (&buff
[pos
], 1, 1023, fich
);
pos += lus;
}
*taille = pos;
buff[pos] = 0;
return buff;
}
char *
lire_message_par_id (char* id, int * taille)
{
char *requete;
asprintf (&requete, \
"select numero_fichier from messages where id = '%s';", \
id);
PGresult * res = executer (requete);
if (0 == PQntuples (res))
return NULL;
char * fich = fichier (id, PQgetvalue(res, 0, 0));
char * resultat = lire_fichier (fich, taille);
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);
PGresult * res = executer (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);
PGresult * res = executer (requete);
int n = PQntuples (res);
if (0 == n)
return NULL;
*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));
ret = ret2;
}
return ret;
}
char *
lister_contis ()
{
PGresult * res = executer ("select nom from contis;");
int n = PQntuples (res);
if (0 == n)
return NULL;
ret[0] = 0;
char * ret2;
int i;
for (i = 0; i < n; i++)
{
asprintf (&ret2, "%s%s\n", ret, PQgetvalue (res, i, 0));
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;
req1[0] = 0;
char * req15;
char * req9;
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);
if (0 < PQntuples(resref))
{
nbref_eff++;
asprintf (&body15, "%s%s, ", body1, msg->refs[i]);
body1 = body15;
asprintf (&req15, \
"%s insert into refs(de, a) values('%s','%s') ;", \
req1, id, msg->refs[i]);
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");
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;
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);
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);
req1 = req15;
}
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);
if (nb_effectif != 0)
/* écriture du fichier */ fichier */
FILE
* fich
= fopen (fichier_corps
, "w"
);
printf ("Le fichier '
%s' a été écrit.\n"
, 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"
);
}
}
char **
nouveau_t ()
{
char ** t
= malloc (LMXSIZ
* sizeof (char*));
int i;
for (i = 0; i < LMXSIZ; i++)
{
};
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);
sscanf (PQgetvalue
(res
, 0, 0), "
%d"
, &numfich
);
numfich++;
char * snumfich;
asprintf (&snumfich, "%d", numfich);
char * fichier_interm = fichier (id, snumfich);
char * snumfichp;
asprintf (&snumfichp, "%d", numfich - 1);
char * fichier_avant = fichier (id, snumfichp);
FILE
* f1
= fopen (fichier_avant
, "r"
);
FILE
* f2
= fopen (fichier_interm
, "w"
);
char * ligne
= malloc (LMXSIZ
);
int ligne_blanche = 0;
char ** t;
int i, n;
strcpy (refer
, "REFERENCES
: "
);
char * refer2;
char * tampon;
{
if (tampon != NULL)
fgets(ligne
, LMXSIZ
, f1
);
if (ligne_blanche == 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]);
};
refer = refer2;
}
asprintf (&tampon, "%s\n", refer);
}
else
{
asprintf (&tampon, "%s", ligne);
}
};
asprintf (&req, \
"%s where id = '%s'", \
"update messages set numero_fichier = 1 + numero_fichier", \
id);
PQexec (conn, 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);
int numfich = 0;
asprintf (&req, "select numero_fichier from messages where id = '%s'", id);
res = PQexec (conn, req);
if (0 == PQntuples (res))
return NULL;
char * snumfichp = PQgetvalue (res, 0, 0);
sscanf (snumfichp
, "
%d"
, &numfich
);
numfich++;
char * snumfichs;
asprintf (&snumfichs, "%d", numfich);
char * fichier_avant = fichier (id, snumfichp);
char * fichier_interm = fichier (id, snumfichs);
FILE
* f1
= fopen (fichier_avant
, "r"
);
FILE
* f2
= fopen (fichier_interm
, "w"
);
char * ligne
= malloc (LMXSIZ
);
int ligne_blanche = 0;
char ** t;
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);
int dans_cible = (0 != PQntuples (res));
char * tampon = NULL;
{
if (tampon != NULL)
fgets (ligne
, LMXSIZ
, f1
);
if (ligne_blanche == 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);
newsgrp = newsgrp2;
}
} else {
asprintf (&newsgrp2, "%s%s, ", newsgrp, t[i]);
newsgrp = newsgrp2;
};
}
newsgrp
[strlen (newsgrp
- 2)] = 0;
asprintf (&tampon, "%s\n", newsgrp);
}
else
{
asprintf (&tampon, "%s", ligne);
}
};
if (dans_cible) {
return id;
};
char * nouv_id = creer_id (date);
char * nouv_fichier = fichier (nouv_id, "0");
rename (fichier_interm
, nouv_fichier
);
asprintf (&req, " select de from refs where a = '%s' ;", id);
res = PQexec (conn, 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);
char * pere = PQgetvalue (res, 0, 0);
char * req2;
{
printf ("Le message '
%s' n'a pas de père.\n"
,id
);
req2[0] = 0;
}
else
{
asprintf (&req, "select fils from messages where id = '%s'; ", pere);
res = PQexec (conn, req);
t = nouveau_t ();
n = parse (PQgetvalue (res, 0, 0) , t, 0, 0);
fils[0] = 0;
char * fils2;
for (i = 0; i < n - 1 ; i++)
{
asprintf (&fils2, "%s%s, ", fils, nouv_id);
else
asprintf (&fils2, "%s%s, ", fils, t[i]);
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);
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);
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);
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);
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);
int n = PQntuples (res);
int i;
for (i = 0; i < n; i++)
{
deplacer_fils_rec (conn, PQgetvalue (res, i, 0), date, cdate, \
source, cible);
}
}
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);
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);
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