Accueil > > > COMPRESSER SES SAUVEGARDES SMSBACKUPRESTORE (ANDROID) EN C AVEC SMSCOMPRESS
COMPRESSER SES SAUVEGARDES SMSBACKUPRESTORE (ANDROID) EN C AVEC SMSCOMPRESS
Information sur la source
Description
Bonjour à tous,
nombreuses sont les personnes qui utilisent un logiciel de sauvegarde de SMS avec android et l'un des plus populaire est SMSBackupRestore (source voir tout en bas).
Le souci de celui-ci c'est qu'il créé de multiples sauvegardes et qu'il ne propose pas des les compresser en une seule.
smscompress est un logiciel en cours de développement qui permettra de charger un ou plusieurs fichier de sauvegarde xml, de les ranger et de le faire un seul fichier.
Pour le moment il ne prend pas en compte les multiples erreurs pouvant venir des fichiers&utilisateurs, il est donc à utiliser avec prudence.
Hésitez pas à faire des commentaires ou corriger des choses qui vous choquent.
Source
- /*************************
- ** SMSCOMPRESS **
- ** Version 1.0.0(b) **
- ** By Thal-Lab **
- ** Where is my mind ? **
- *************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "loadsms.h"
- /*
- **Ce programme est un complément à l'application SMSBACKUP.APK, logiciel pour Gphone sous android.
- **Principe :
- **Les sauvegardes se font sur des fichiers XML, qui se cumulent si elles sont faites régulièrement.
- **Entrée : un/des fichier(s) XML,
- **Sorti : Un fichier XML sans doublon rangé par date et d'ordre croissant,
- **Variable : Seront précisés au cours du code source,
- **Le programme se devra d'être le plus simple possible et faire le travail sans trop de complexité,
- **Il pourra accepter de nombreux arguments correspondant aux nombreux fichiers d'entrées.
- **Aucun commentaire sur mon anglais S.V.P. (lol)
- */
- int main(int argc, char *argv[])
- {
- /*
- **Vérification des erreurs d'arguments
- **Le logiciel se fermera si les conditions d'utilisations ne sont pas respéctées, c'est-à-dire :
- **Deux arguments minimum dont :
- **-Le premier la destination de sauvergarde,
- **-Le second la source de sauvegarde
- **Il affichera éventuellement un mini manuelle.
- */
- if(argv[1]== NULL || argv[2] == NULL)
- {
- printf("Missing argument error, the program will close.\n");
- printf("The application is used as follows:\n"
- "smscompress destination source1 source2 ... SourceN.\n"
- "example : smscompress /home/name/jhon-doe.xml /media/gphone/smsbackup/*\n");
- return 0;
- }
- /*
- **Création de deux variables à allocation dynamique :
- **oldbackup : enregistrement de toutes les sauvegardes de tous les fichiers, sans en-tête,
- ** Sans la balise smses.
- **newbackup : Sauvegarde prête à être utilisé et enregistré sur le fichier elle contient :
- ** de nouvelles en-têtes et une balise smses contenant le nouveau nombre de sms
- ** le tout rangé par ordre chronologique croissant.
- **Les deux variables pèsent au début SIZE_ALLOC octets chacune.
- */
- char *oldbackup = NULL;
- memmalloc(oldbackup, SIZE_ALLOC);//alloué
- if (oldbackup == NULL)//Si l'allocation a raté, fin.
- {
- printf("Memory allocation problem, the program needs to close.\n");
- exit(0);
- }
- char *newbackup = NULL;
- memmalloc(newbackup, SIZE_ALLOC);//alloué
- if (newbackup == NULL)//Si l'allocation a raté, fin.
- {
- printf("Memory allocation problem, the program needs to close.\n");
- exit(0);
- }
- char select = 0;//Cette variable à pour but de proposer à l'utilisateur des choix
- /*
- **Vérification de l'existence du fichier de destination
- **Si le fichier existe déjà, le programme demandera alors s'il peut l'écraser
- **Le cas contraire le programme se fermera pour laisser entrer de nouveaux arguments
- */
- FILE *destination = NULL;
- destination = fopen(argv[1], "rb");
- if (destination != NULL)
- {
- while(select != 'o')
- {
- printf("Do you want to overwrite the file \"%s\"? ", argv[1]);
- scanf("%c", &select);
- if(select == 'n')
- {
- printf("You do not want to overwrite the file, the program will close.\n");
- return 0;
- }
- else if(select == 'o')
- {
- destination = fopen(argv[1], "wb+");
- if(destination == NULL)
- {
- printf("Error writing file, the program will close.");
- return 0;
- }
- else
- {
- printf("Writing the file was successful.\n");
- }
- }
- else
- {
- select = 0;
- }
- }
- }
- else
- {
- destination = fopen(argv[1], "wb+");
- if(destination == NULL)
- {
- printf("Error writing file, the program will close.");
- return 0;
- }
- }
- /*
- **Boucle de vérification d'existence des arguments
- **Ici le programme ne s'arrêtera pas si les sources sont mauvaises, il passera simplement à une autre
- **Si toutes les sources sont mauvaises, que la sauvegarde n'a pas lieu, le programme fera simplement une sauvegarde vide.
- **Dans la boucle i est initialisé à 2, car :
- **-Argument 0 : nom du programme,
- **-Argument 1 : nom de destination,
- **-Argument 2 : nom de la première source.
- */
- int i,//Variable de boucle for i, non initialisée
- j,//Variable de boucle non définie
- k,//Variable de boucle non définie
- gchar,//lecteur de caractère pour la fonction fgetc
- sizebackup = 0;//Evite des débordements mémoire
- /*
- **Ce buffer contient une balise sms entière, estimé par ce calcul à :
- **size_buffer = ( 160 * 50 ) + ( 160 * 10 ), large
- */
- char buffer[SIZE_BUFFER * sizeof(char)];
- /*
- **Déclaration de la structure IntElementSMS
- **Elle servira à de multiple tache de manipulation
- **Déclaration de la structure d'allocation de mémoire
- **Initialisation de la variable memtest à 1 car 1 fois SIZE_ALLOC ont été alloué
- */
- ElementSMS sms;
- int memtest = 1;
- sms.countsms = 0;
- for(i = 2; i<= argc-1; i++)
- {
- /*
- **Prépraration du fichier source suivi de la vérification de son existence
- **En cas d'erreur le programme continue la boucle en attendant qu'il n'y ai plus d'argument(s)
- **Si aucune erreur se fait, lancement de la compression des fichiers.
- */
- FILE *source = NULL;
- printf("Opening of \"%s\", ",argv[i]);//Affichage à l'utilisateur de l'avancement
- source = fopen(argv[i], "rb+");
- if(source == NULL || extension(argv[i]) != 1)
- {
- /*
- **Le programme donnera seulement l'argument erroné et la ligne lui correspondant
- **En fin de boucle le programme relancera soit un autre argument,
- **Soit il finira l'enregistrement.
- */
- printf("The file does not exist and/or extend is bad, argument \"%s\" number %d is not valide \n", argv[i], i);
- }
- else
- {
- printf("Current reading, ");//Affichage à l'utilisateur de l'avancement
- j = 0,//Boucle non défini, on met j à 0
- k = 0,//Boucle non défini, on met k à 0
- initElementSMS(&sms);
- initab(buffer, SIZE_BUFFER);
- /*
- **Cette boucle va permettre de supprimer les balise d'en-tête
- **Et ranger de manière compressé la sauvegarde
- */
- do
- {
- gchar = fgetc(source);//Lecture du caractère
- if(gchar == '<' || sms.openbalise == TRUE)//Si la balise s'ouvre ou si la balise est déjà ouverte
- {
- sms.openbalise =TRUE;
- buffer[j++] = gchar;//mise dans le buffer
- if(cmp_b(buffer,"<?xml",5) == 0 && sms.headxml == FALSE && sms.balisesmses == FALSE)//Détection de la balise <? ?>
- {
- /*
- **Suppression de cette balise qui peut-être handicapant pour la suite
- **Elle n'est plus utile le temps de la compression
- */
- while(gchar != '>')
- {
- gchar = fgetc(source);
- }
- sms.headxml = TRUE;
- j -= 5;
- }
- if(cmp_b(buffer,"<smses",6) == 0 && sms.balisesmses == FALSE && sms.headxml == TRUE)
- {
- /*
- **Suppression de la balise <smses>
- **Elle n'est plus utile le temps de la compression
- */
- while(gchar != '>')
- {
- gchar = fgetc(source);
- }
- sms.balisesmses = TRUE;
- j -= 6;
- }
- if(cmp_b(buffer,"<sms ",5) == 0 && sms.headxml == TRUE && sms.balisesmses == TRUE)
- {
- while(gchar != '>')
- {
- gchar = fgetc(source);
- buffer[j++] = gchar;
- }
- }
- if(cmp_b(buffer,"</smses>",8) == 0 && sms.balisesmses == TRUE && sms.headxml == TRUE)
- {
- /*
- **Suppression de la balise </smses>
- **Elle n'est plus utile le temps de la compression
- */
- j -= 8;
- }
- }
- if(gchar == '>' && sms.openbalise == TRUE)
- {
- /*
- **Le programme ferme le buffer par \0
- **Il augmente la taille de oldbackup
- **Il réallou autant que nécessaire la mémoire
- */
- buffer[j*sizeof(char*)]='\0';//ça parrait bête mais parfois ça sauve un bug !
- sms.bufferint = readargdate(buffer);
- if(sms.bufferint != ERROR_F && sms.headxml == TRUE && sms.balisesmses == TRUE)
- {
- if((single(sms.dateorder, sms.countsms, sms.bufferint)) == TRUE)
- {
- sms.dateorder[sms.countsms++] = sms.bufferint;
- sizebackup += j;
- while(((memtest)*(SIZE_ALLOC))>=(sizebackup))
- {
- memrealloc(oldbackup, memtest++);//Réalouer (SIZE_ALLOC * 4) Octet
- }
- sprintf(oldbackup, "%s%s",oldbackup, buffer);
- }
- }
- j = 0, sms.openbalise = FALSE;
- }
- }while(gchar != EOF);
- printf("0k.\n");
- }
- close(source);
- }
- printf("Storing date in ascending order during...\n");
- ascendingdate(sms.dateorder, sms.countsms);
- /*
- **Le tri des sms ne peut se faire en une fois, ça rendrait le programme trop lourd à écrire x)
- **La boucle rangera les sms gràce dateorder dans newbackup
- **Un allocation dynamique sera faite sur newbackup en début de programme
- **il ne sera plus question ensuite de la remodifier, realloc étant trop gourmand
- **La taille de realloc est de la taille de oldbackup + le nombre de sms x 3 c'est attire, deux espace et un \n
- **Et de MAX_BALISE une estimation de la taille des balises restantent
- **La fonction est un peu désorganisée mais elle fonctionne, c'est important !
- */
- printf("loading ...\n");
- memnewrealloc(newbackup, ((strlen(oldbackup) + MAX_BALISE + (sms.countsms * 3))));
- initElementSMS(&sms);
- sms.bufferint = 0, newbackup[0] = '\0';
- printf("Text Analysis in progress ...\n");
- for(k = 0; k <= sms.countsms; k++)
- {
- i = 0, j = 0;
- while(sms.dateorder[k] != sms.bufferint)
- {
- if(oldbackup[i] == '<' || sms.openbalise == TRUE)
- {
- sms.openbalise = TRUE;
- buffer[j++] = oldbackup[i];
- }
- if(oldbackup[i] == '>' && sms.openbalise == TRUE)
- {
- sms.openbalise = FALSE;
- buffer[j] = '\0';
- sms.bufferint = readargdate(buffer);
- if(sms.dateorder[k] == sms.bufferint)
- {
- sprintf(newbackup, "%s %s\n", newbackup, buffer);//on note bien la préparation au nouveau fichier XML
- }
- j = 0;
- }
- i++;
- }
- }
- free(oldbackup);//Libèration de la mémoire
- oldbackup = NULL;//Forcer
- /*
- **Fermeture du programme
- **Libération de la mémoire
- */
- printf("Writing the new xml file ...\n");
- fprintf(destination,"%s%s%d%s%s%s", HEAD, BODY_SMSES, sms.countsms, BODY_SMSES_CLOSE, newbackup, BODY_END_SMSES);//on remarque l'ajout des balises
- close(destination);
- free(newbackup);
- newbackup = NULL;
- printf("Finish, you have analyzed %d SMS. The program will close, bye.\n", sms.countsms);
- return 0;
- }
- /***************************************************************************************************************************************/
- //loadsms.c
- /***************************************************************************************************************************************/
- #include <string.h>
- #include "loadsms.h"
- //Initialiser un tableau char à 0 sur n caractère.
- void initab(char tab[], int n)
- {
- int i;
- for(i = 0 ;i <= n; i++)
- {
- tab[i] = 0;
- }
- }
- /*
- **La fonction va changer un char en int
- **Cette fonction à pour but de lire un attribut "date" écrit dans le buffer
- **Elle revoit un int et avec la formule : n = (n * 10) + chartoint
- **On convertira un string en int facilement.
- */
- int chartoint(int charint)
- {
- if(charint=='0')
- return 0;
- if(charint=='1')
- return 1;
- if(charint=='2')
- return 2;
- if(charint=='3')
- return 3;
- if(charint=='4')
- return 4;
- if(charint=='5')
- return 5;
- if(charint=='6')
- return 6;
- if(charint=='7')
- return 7;
- if(charint=='8')
- return 8;
- if(charint=='9')
- return 9;
- return -1;
- }
- //Cette fonction range par ordre croissant les dates
- void ascendingdate(double tab[], int max)
- {
- int i,j;
- for(i = 0; i <= (max - 1); i++)
- {
- for(j = 0 + 1; j <= (max - 1); j++)
- if(tab[i] < tab[j])
- {
- exchange(tab, i, j);
- }
- if(tab[i] > tab[j])
- {
- exchange(tab, j, i);
- }
- }
- }
- /*
- **Cette fonction va vérifier si dans un table une valeur est unique
- **La fonction renverra TRUE si c'est vérifié ou FALSE si cela n'est pas
- */
- int single(double tab[], int max, double singlevaleur)
- {
- int i;
- for(i = 0; i <= max; i++)
- {
- if(singlevaleur == tab[i])
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- /*
- **Ce tableau permet de lire et analyser l'attribut "date" dans le buffer
- **La fonction peut prendre énormement de temps
- **Elle renvoie -1 si il y a une erreur ou la valeur de la date si ça se passe bien
- */
- double readargdate(char tab[])
- {
- int i, j;
- double n = 0;
- for(i = 0; (strncmp((tab + i), "date=\"", 6)) != 0; i++)
- {
- if(tab[i] == '\0')
- {
- return ERROR_F;
- }
- }
- for(j = i + 6; tab[j] != '"'; j++)
- {
- if(chartoint(tab[j]) == ERROR_F)
- {
- return ERROR_F;
- }
- n = (n * 10) + chartoint(tab[j]);
- }
- return n;
- }
- //Echanger la valeur b/a et a/b dans le tableau
- void exchange(double tab[], int a, int b)
- {
- double n;
- n = tab[a];
- tab[a] = tab[b];
- tab[b] = n;
- }
- /*
- **Fonction pour initialiser la structure ElementSMS, pointeur utile ici.
- **openbalise : Ouverture(TRUE) de balise (<) et fermeture(FALSE) de balise (>).
- **openvar : Ouverture(TRUE) de valeur d'attrivut (<) et fermeture(FALSE) de valeur d'attribut (>).
- **headxml : Balise d'en-tête <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> croisé ou non.
- *balisesmses : Balise <smses/> croisé ou non.
- */
- void initElementSMS(ElementSMS *tmp)
- {
- tmp->openbalise = FALSE,
- tmp->openvar = FALSE,
- tmp->headxml = FALSE,
- tmp->balisesmses = FALSE;
- }
- //Fonction pour la lecture des extensions et éliminer les fichiers non XML, peut-on faire plus simple ?
- int extension(char *ext)
- {
- int i = strlen(ext);
- if(strcmp((ext + i - 4), ".xml") == 0 || strcmp((ext + i - 4), ".XML") == 0)
- {
- return TRUE;
- }
- return FALSE;
- }
- /*
- **Fonction pour la lecture des balises moins performante que strncmp mais évite un bug de la fonction
- **c'est moche de faire strncmp à sa "sauce".
- */
- int cmp_b(const char *s1, const char *s2, int sizechar)
- {
- int i;
- for(i = 0;((*s1++) == (*s2++)); ++i)
- {
- if(i == sizechar)
- {
- for(;((*s1--) == (*s2--));--i)
- {
- if(i <= 0)
- {
- return TRUE;
- }
- }
- }
- }
- return FALSE;
- }
- /***************************************************************************************************************************************/
- //loadsms.h
- /***************************************************************************************************************************************/
- #ifndef EXPORTSMS_H
- #define EXPORTSMS_H
- #include <stdlib.h>
- //Booléens très utile
- #define FALSE 0
- #define TRUE 1
- /*
- **Ces variables vont définir la taille du buffer
- **On prend 160 la taille maximum d'un SMS
- **On suppose que les messages de 50 sont le maximum qu'un utilisateur va envoyé
- **On suppose aussi que les balises et leur contenu seront de la taille de :
- **10 SMS au maximum. Le tout est large.
- */
- #define SIZE_SMS 160
- #define SEND_SMS 50
- #define SIZE_BALISE (SIZE_SMS * 10)
- #define SIZE_BUFFER ((SIZE_SMS * SEND_SMS) + SIZE_BALISE)
- /*
- **Définition des mémoires utilisées
- **Diverses macros pour l'allocation et la réallocation
- */
- #define MAX_BALISE 1024
- #define SIZE_ALLOC 16384
- #define DATE_ORDER 200000 //ça represente quand même 200k SMS, c'est énorme
- #define memmalloc(var, n)((var) = malloc((n) * (sizeof(*var))))
- #define memrealloc(var, n)((var) = realloc((var), ((n) * (SIZE_ALLOC)) * (sizeof(*var))))
- #define memnewrealloc(var, n)((var) = realloc((var), ((n) * (sizeof(*var)))))
- /*
- **Définition de constante pour la création de la nouvelle sauvegarde
- **Pour le moment elles sont peu nombreuse
- */
- #define HEAD "<?xml version=\'1.0\' encoding=\'UTF-8\' standalone=\'yes' ?>\n"
- #define BODY_SMSES "<smses count=\""
- #define BODY_END_SMSES "</smses>"
- #define BODY_SMSES_CLOSE "\">\n"
- //les erreurs possibles
- #define ERROR_F -1
- /*
- **Structure pour la gestion des SMS :
- **openbalise, Variable permettant de savoir si une balise est ouverte ou non
- **openvar, Variable permettant de savoir si un attribut est cours de lecture ou non
- **headxml, Variable d'en-tête de balise, si elle a été vu ou non (<? ?>)
- **countsms, Variable pour compter le nombre de SMS traité et prêt à être enregistrée
- **balisesmses, Balise <smses/> lu ou non.
- */
- typedef struct ElementSMS{
- int openbalise,
- openvar,
- headxml,
- countsms,
- balisesmses;
-
- double dateorder[DATE_ORDER],
- bufferint;
- }ElementSMS;
- //Header de fonction
- void initab(char tab[], int n);
- int chartoint(int charint);
- void ascendingdate(double tab[], int max);
- int single(double tab[], int max, double singlevaleur);
- double readargdate(char tab[]);
- void exchange(double tab[], int a, int b);
- void initElementSMS(ElementSMS *tmp);
- int extension(char *ext);
- int cmp_b(const char *s1, const char *s2, int sizechar);
- #endif
/*************************
** SMSCOMPRESS **
** Version 1.0.0(b) **
** By Thal-Lab **
** Where is my mind ? **
*************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "loadsms.h"
/*
**Ce programme est un complément à l'application SMSBACKUP.APK, logiciel pour Gphone sous android.
**Principe :
**Les sauvegardes se font sur des fichiers XML, qui se cumulent si elles sont faites régulièrement.
**Entrée : un/des fichier(s) XML,
**Sorti : Un fichier XML sans doublon rangé par date et d'ordre croissant,
**Variable : Seront précisés au cours du code source,
**Le programme se devra d'être le plus simple possible et faire le travail sans trop de complexité,
**Il pourra accepter de nombreux arguments correspondant aux nombreux fichiers d'entrées.
**Aucun commentaire sur mon anglais S.V.P. (lol)
*/
int main(int argc, char *argv[])
{
/*
**Vérification des erreurs d'arguments
**Le logiciel se fermera si les conditions d'utilisations ne sont pas respéctées, c'est-à-dire :
**Deux arguments minimum dont :
**-Le premier la destination de sauvergarde,
**-Le second la source de sauvegarde
**Il affichera éventuellement un mini manuelle.
*/
if(argv[1]== NULL || argv[2] == NULL)
{
printf("Missing argument error, the program will close.\n");
printf("The application is used as follows:\n"
"smscompress destination source1 source2 ... SourceN.\n"
"example : smscompress /home/name/jhon-doe.xml /media/gphone/smsbackup/*\n");
return 0;
}
/*
**Création de deux variables à allocation dynamique :
**oldbackup : enregistrement de toutes les sauvegardes de tous les fichiers, sans en-tête,
** Sans la balise smses.
**newbackup : Sauvegarde prête à être utilisé et enregistré sur le fichier elle contient :
** de nouvelles en-têtes et une balise smses contenant le nouveau nombre de sms
** le tout rangé par ordre chronologique croissant.
**Les deux variables pèsent au début SIZE_ALLOC octets chacune.
*/
char *oldbackup = NULL;
memmalloc(oldbackup, SIZE_ALLOC);//alloué
if (oldbackup == NULL)//Si l'allocation a raté, fin.
{
printf("Memory allocation problem, the program needs to close.\n");
exit(0);
}
char *newbackup = NULL;
memmalloc(newbackup, SIZE_ALLOC);//alloué
if (newbackup == NULL)//Si l'allocation a raté, fin.
{
printf("Memory allocation problem, the program needs to close.\n");
exit(0);
}
char select = 0;//Cette variable à pour but de proposer à l'utilisateur des choix
/*
**Vérification de l'existence du fichier de destination
**Si le fichier existe déjà, le programme demandera alors s'il peut l'écraser
**Le cas contraire le programme se fermera pour laisser entrer de nouveaux arguments
*/
FILE *destination = NULL;
destination = fopen(argv[1], "rb");
if (destination != NULL)
{
while(select != 'o')
{
printf("Do you want to overwrite the file \"%s\"? ", argv[1]);
scanf("%c", &select);
if(select == 'n')
{
printf("You do not want to overwrite the file, the program will close.\n");
return 0;
}
else if(select == 'o')
{
destination = fopen(argv[1], "wb+");
if(destination == NULL)
{
printf("Error writing file, the program will close.");
return 0;
}
else
{
printf("Writing the file was successful.\n");
}
}
else
{
select = 0;
}
}
}
else
{
destination = fopen(argv[1], "wb+");
if(destination == NULL)
{
printf("Error writing file, the program will close.");
return 0;
}
}
/*
**Boucle de vérification d'existence des arguments
**Ici le programme ne s'arrêtera pas si les sources sont mauvaises, il passera simplement à une autre
**Si toutes les sources sont mauvaises, que la sauvegarde n'a pas lieu, le programme fera simplement une sauvegarde vide.
**Dans la boucle i est initialisé à 2, car :
**-Argument 0 : nom du programme,
**-Argument 1 : nom de destination,
**-Argument 2 : nom de la première source.
*/
int i,//Variable de boucle for i, non initialisée
j,//Variable de boucle non définie
k,//Variable de boucle non définie
gchar,//lecteur de caractère pour la fonction fgetc
sizebackup = 0;//Evite des débordements mémoire
/*
**Ce buffer contient une balise sms entière, estimé par ce calcul à :
**size_buffer = ( 160 * 50 ) + ( 160 * 10 ), large
*/
char buffer[SIZE_BUFFER * sizeof(char)];
/*
**Déclaration de la structure IntElementSMS
**Elle servira à de multiple tache de manipulation
**Déclaration de la structure d'allocation de mémoire
**Initialisation de la variable memtest à 1 car 1 fois SIZE_ALLOC ont été alloué
*/
ElementSMS sms;
int memtest = 1;
sms.countsms = 0;
for(i = 2; i<= argc-1; i++)
{
/*
**Prépraration du fichier source suivi de la vérification de son existence
**En cas d'erreur le programme continue la boucle en attendant qu'il n'y ai plus d'argument(s)
**Si aucune erreur se fait, lancement de la compression des fichiers.
*/
FILE *source = NULL;
printf("Opening of \"%s\", ",argv[i]);//Affichage à l'utilisateur de l'avancement
source = fopen(argv[i], "rb+");
if(source == NULL || extension(argv[i]) != 1)
{
/*
**Le programme donnera seulement l'argument erroné et la ligne lui correspondant
**En fin de boucle le programme relancera soit un autre argument,
**Soit il finira l'enregistrement.
*/
printf("The file does not exist and/or extend is bad, argument \"%s\" number %d is not valide \n", argv[i], i);
}
else
{
printf("Current reading, ");//Affichage à l'utilisateur de l'avancement
j = 0,//Boucle non défini, on met j à 0
k = 0,//Boucle non défini, on met k à 0
initElementSMS(&sms);
initab(buffer, SIZE_BUFFER);
/*
**Cette boucle va permettre de supprimer les balise d'en-tête
**Et ranger de manière compressé la sauvegarde
*/
do
{
gchar = fgetc(source);//Lecture du caractère
if(gchar == '<' || sms.openbalise == TRUE)//Si la balise s'ouvre ou si la balise est déjà ouverte
{
sms.openbalise =TRUE;
buffer[j++] = gchar;//mise dans le buffer
if(cmp_b(buffer,"<?xml",5) == 0 && sms.headxml == FALSE && sms.balisesmses == FALSE)//Détection de la balise <? ?>
{
/*
**Suppression de cette balise qui peut-être handicapant pour la suite
**Elle n'est plus utile le temps de la compression
*/
while(gchar != '>')
{
gchar = fgetc(source);
}
sms.headxml = TRUE;
j -= 5;
}
if(cmp_b(buffer,"<smses",6) == 0 && sms.balisesmses == FALSE && sms.headxml == TRUE)
{
/*
**Suppression de la balise <smses>
**Elle n'est plus utile le temps de la compression
*/
while(gchar != '>')
{
gchar = fgetc(source);
}
sms.balisesmses = TRUE;
j -= 6;
}
if(cmp_b(buffer,"<sms ",5) == 0 && sms.headxml == TRUE && sms.balisesmses == TRUE)
{
while(gchar != '>')
{
gchar = fgetc(source);
buffer[j++] = gchar;
}
}
if(cmp_b(buffer,"</smses>",8) == 0 && sms.balisesmses == TRUE && sms.headxml == TRUE)
{
/*
**Suppression de la balise </smses>
**Elle n'est plus utile le temps de la compression
*/
j -= 8;
}
}
if(gchar == '>' && sms.openbalise == TRUE)
{
/*
**Le programme ferme le buffer par \0
**Il augmente la taille de oldbackup
**Il réallou autant que nécessaire la mémoire
*/
buffer[j*sizeof(char*)]='\0';//ça parrait bête mais parfois ça sauve un bug !
sms.bufferint = readargdate(buffer);
if(sms.bufferint != ERROR_F && sms.headxml == TRUE && sms.balisesmses == TRUE)
{
if((single(sms.dateorder, sms.countsms, sms.bufferint)) == TRUE)
{
sms.dateorder[sms.countsms++] = sms.bufferint;
sizebackup += j;
while(((memtest)*(SIZE_ALLOC))>=(sizebackup))
{
memrealloc(oldbackup, memtest++);//Réalouer (SIZE_ALLOC * 4) Octet
}
sprintf(oldbackup, "%s%s",oldbackup, buffer);
}
}
j = 0, sms.openbalise = FALSE;
}
}while(gchar != EOF);
printf("0k.\n");
}
close(source);
}
printf("Storing date in ascending order during...\n");
ascendingdate(sms.dateorder, sms.countsms);
/*
**Le tri des sms ne peut se faire en une fois, ça rendrait le programme trop lourd à écrire x)
**La boucle rangera les sms gràce dateorder dans newbackup
**Un allocation dynamique sera faite sur newbackup en début de programme
**il ne sera plus question ensuite de la remodifier, realloc étant trop gourmand
**La taille de realloc est de la taille de oldbackup + le nombre de sms x 3 c'est attire, deux espace et un \n
**Et de MAX_BALISE une estimation de la taille des balises restantent
**La fonction est un peu désorganisée mais elle fonctionne, c'est important !
*/
printf("loading ...\n");
memnewrealloc(newbackup, ((strlen(oldbackup) + MAX_BALISE + (sms.countsms * 3))));
initElementSMS(&sms);
sms.bufferint = 0, newbackup[0] = '\0';
printf("Text Analysis in progress ...\n");
for(k = 0; k <= sms.countsms; k++)
{
i = 0, j = 0;
while(sms.dateorder[k] != sms.bufferint)
{
if(oldbackup[i] == '<' || sms.openbalise == TRUE)
{
sms.openbalise = TRUE;
buffer[j++] = oldbackup[i];
}
if(oldbackup[i] == '>' && sms.openbalise == TRUE)
{
sms.openbalise = FALSE;
buffer[j] = '\0';
sms.bufferint = readargdate(buffer);
if(sms.dateorder[k] == sms.bufferint)
{
sprintf(newbackup, "%s %s\n", newbackup, buffer);//on note bien la préparation au nouveau fichier XML
}
j = 0;
}
i++;
}
}
free(oldbackup);//Libèration de la mémoire
oldbackup = NULL;//Forcer
/*
**Fermeture du programme
**Libération de la mémoire
*/
printf("Writing the new xml file ...\n");
fprintf(destination,"%s%s%d%s%s%s", HEAD, BODY_SMSES, sms.countsms, BODY_SMSES_CLOSE, newbackup, BODY_END_SMSES);//on remarque l'ajout des balises
close(destination);
free(newbackup);
newbackup = NULL;
printf("Finish, you have analyzed %d SMS. The program will close, bye.\n", sms.countsms);
return 0;
}
/***************************************************************************************************************************************/
//loadsms.c
/***************************************************************************************************************************************/
#include <string.h>
#include "loadsms.h"
//Initialiser un tableau char à 0 sur n caractère.
void initab(char tab[], int n)
{
int i;
for(i = 0 ;i <= n; i++)
{
tab[i] = 0;
}
}
/*
**La fonction va changer un char en int
**Cette fonction à pour but de lire un attribut "date" écrit dans le buffer
**Elle revoit un int et avec la formule : n = (n * 10) + chartoint
**On convertira un string en int facilement.
*/
int chartoint(int charint)
{
if(charint=='0')
return 0;
if(charint=='1')
return 1;
if(charint=='2')
return 2;
if(charint=='3')
return 3;
if(charint=='4')
return 4;
if(charint=='5')
return 5;
if(charint=='6')
return 6;
if(charint=='7')
return 7;
if(charint=='8')
return 8;
if(charint=='9')
return 9;
return -1;
}
//Cette fonction range par ordre croissant les dates
void ascendingdate(double tab[], int max)
{
int i,j;
for(i = 0; i <= (max - 1); i++)
{
for(j = 0 + 1; j <= (max - 1); j++)
if(tab[i] < tab[j])
{
exchange(tab, i, j);
}
if(tab[i] > tab[j])
{
exchange(tab, j, i);
}
}
}
/*
**Cette fonction va vérifier si dans un table une valeur est unique
**La fonction renverra TRUE si c'est vérifié ou FALSE si cela n'est pas
*/
int single(double tab[], int max, double singlevaleur)
{
int i;
for(i = 0; i <= max; i++)
{
if(singlevaleur == tab[i])
{
return FALSE;
}
}
return TRUE;
}
/*
**Ce tableau permet de lire et analyser l'attribut "date" dans le buffer
**La fonction peut prendre énormement de temps
**Elle renvoie -1 si il y a une erreur ou la valeur de la date si ça se passe bien
*/
double readargdate(char tab[])
{
int i, j;
double n = 0;
for(i = 0; (strncmp((tab + i), "date=\"", 6)) != 0; i++)
{
if(tab[i] == '\0')
{
return ERROR_F;
}
}
for(j = i + 6; tab[j] != '"'; j++)
{
if(chartoint(tab[j]) == ERROR_F)
{
return ERROR_F;
}
n = (n * 10) + chartoint(tab[j]);
}
return n;
}
//Echanger la valeur b/a et a/b dans le tableau
void exchange(double tab[], int a, int b)
{
double n;
n = tab[a];
tab[a] = tab[b];
tab[b] = n;
}
/*
**Fonction pour initialiser la structure ElementSMS, pointeur utile ici.
**openbalise : Ouverture(TRUE) de balise (<) et fermeture(FALSE) de balise (>).
**openvar : Ouverture(TRUE) de valeur d'attrivut (<) et fermeture(FALSE) de valeur d'attribut (>).
**headxml : Balise d'en-tête <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> croisé ou non.
*balisesmses : Balise <smses/> croisé ou non.
*/
void initElementSMS(ElementSMS *tmp)
{
tmp->openbalise = FALSE,
tmp->openvar = FALSE,
tmp->headxml = FALSE,
tmp->balisesmses = FALSE;
}
//Fonction pour la lecture des extensions et éliminer les fichiers non XML, peut-on faire plus simple ?
int extension(char *ext)
{
int i = strlen(ext);
if(strcmp((ext + i - 4), ".xml") == 0 || strcmp((ext + i - 4), ".XML") == 0)
{
return TRUE;
}
return FALSE;
}
/*
**Fonction pour la lecture des balises moins performante que strncmp mais évite un bug de la fonction
**c'est moche de faire strncmp à sa "sauce".
*/
int cmp_b(const char *s1, const char *s2, int sizechar)
{
int i;
for(i = 0;((*s1++) == (*s2++)); ++i)
{
if(i == sizechar)
{
for(;((*s1--) == (*s2--));--i)
{
if(i <= 0)
{
return TRUE;
}
}
}
}
return FALSE;
}
/***************************************************************************************************************************************/
//loadsms.h
/***************************************************************************************************************************************/
#ifndef EXPORTSMS_H
#define EXPORTSMS_H
#include <stdlib.h>
//Booléens très utile
#define FALSE 0
#define TRUE 1
/*
**Ces variables vont définir la taille du buffer
**On prend 160 la taille maximum d'un SMS
**On suppose que les messages de 50 sont le maximum qu'un utilisateur va envoyé
**On suppose aussi que les balises et leur contenu seront de la taille de :
**10 SMS au maximum. Le tout est large.
*/
#define SIZE_SMS 160
#define SEND_SMS 50
#define SIZE_BALISE (SIZE_SMS * 10)
#define SIZE_BUFFER ((SIZE_SMS * SEND_SMS) + SIZE_BALISE)
/*
**Définition des mémoires utilisées
**Diverses macros pour l'allocation et la réallocation
*/
#define MAX_BALISE 1024
#define SIZE_ALLOC 16384
#define DATE_ORDER 200000 //ça represente quand même 200k SMS, c'est énorme
#define memmalloc(var, n)((var) = malloc((n) * (sizeof(*var))))
#define memrealloc(var, n)((var) = realloc((var), ((n) * (SIZE_ALLOC)) * (sizeof(*var))))
#define memnewrealloc(var, n)((var) = realloc((var), ((n) * (sizeof(*var)))))
/*
**Définition de constante pour la création de la nouvelle sauvegarde
**Pour le moment elles sont peu nombreuse
*/
#define HEAD "<?xml version=\'1.0\' encoding=\'UTF-8\' standalone=\'yes' ?>\n"
#define BODY_SMSES "<smses count=\""
#define BODY_END_SMSES "</smses>"
#define BODY_SMSES_CLOSE "\">\n"
//les erreurs possibles
#define ERROR_F -1
/*
**Structure pour la gestion des SMS :
**openbalise, Variable permettant de savoir si une balise est ouverte ou non
**openvar, Variable permettant de savoir si un attribut est cours de lecture ou non
**headxml, Variable d'en-tête de balise, si elle a été vu ou non (<? ?>)
**countsms, Variable pour compter le nombre de SMS traité et prêt à être enregistrée
**balisesmses, Balise <smses/> lu ou non.
*/
typedef struct ElementSMS{
int openbalise,
openvar,
headxml,
countsms,
balisesmses;
double dateorder[DATE_ORDER],
bufferint;
}ElementSMS;
//Header de fonction
void initab(char tab[], int n);
int chartoint(int charint);
void ascendingdate(double tab[], int max);
int single(double tab[], int max, double singlevaleur);
double readargdate(char tab[]);
void exchange(double tab[], int a, int b);
void initElementSMS(ElementSMS *tmp);
int extension(char *ext);
int cmp_b(const char *s1, const char *s2, int sizechar);
#endif
Conclusion
J'ai vu beaucoup de genre chercher à savoir comment lire une balise XML en C, ici il y a une réponse.
Si des améliorations sont possibles (et il y en a !), vous gênez pas :).
Logiciel smsbackup&restore:
http://android.riteshsahu.com/ apps/sms-backup-restore
Thal-Lab.
Historique
- 05 février 2011 14:26:53 :
- Les commentaires s'affichaient pas bien.
- 05 février 2011 14:31:19 :
- Les commentaires s'affichaient pas bien.
- 05 février 2011 15:25:12 :
- Modification des commentaires, mise à jour du zip.
- 07 février 2011 13:45:51 :
- Modification du code source & du Zip.
- 07 février 2011 15:18:40 :
- amélioration des recherches et affichage de la source du logiciel SMSBackupRestore.
- 08 février 2011 12:26:24 :
- Les fonctions fonctionnent mieux, correction de quelques bugs, mise à jours du zip.
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
libxml2 et C [ par boualiasma ]
Bonjour, J'ai bien installé Libxml2 dans mon projet de travail. Il me reste comment je vais l'utiliser dans mon programme C. De plus, je ne trouve pa
suppression des balise XML [ par abdoulax ]
Bonjour,<NOTIFICATION ver="2" id="2" siteid="0" siteurl="http://g.live.com/"><TO name="email@email.com" pid="0x0:0x0"/><MSG pri="1" id=
XML / C [ par schole05 ]
bonjour,j'aimerais pouvoir manipuler des fichiers xml à travers mon programme en C, comme on pourrait le faire pour une mini base de données. Au fil d
ajouter le bibliothèque XML et un appel à une commande dos dans un programme C sous Visual Studio [ par boualiasma ]
Bonjour, Je suis entrain de programmer en C avec Visual studio 2008 sous Windows XP. Je voudrais parser un fichier XML dans mon programme C. J'ai trou
Disparition du programme dans la barre des taches [ par Grenapeel ]
Bonjour,je rencontre actuellement le probleme suivant : J'ai un programme (MFC) avec une premiere fenetre qui s'ouvre ou on choisit le type de distanc
C et Mysql [ par boualiasma ]
Salut,-Je voudrais établir dans mon programme C une connexion à une base de données crée sous Mysql(j'ai instalé EasyPHP-3.0-setup).Sachant que mon pr
Besoin d'aide pour un programme [ par milka77 ]
Bonjour,j'essaye de créer un programme qui peut copier tout ce qu'un fichier contient vers un autre fichier txt.Si vous pouviez m'aider car je ne sais
taille tableau de structure. [ par macbang ]
Bonjour, Mon programme fonctionne très bien pour le moment. Le seul hic c'est que j'ouvre un fichier texte pour le découper ligne par ligne. Pour l'in
convertir un fichier texte en fichier XML. [ par boualiasma ]
Salut à tous !Je suis en train d'essayer de convertir un fichier texte en xml.Ce fichier texte est structuré, et j'ai donc un identifiant en début de
ajouter une librairie utilisateur à un programme C sous Visual Studio 2008 [ par boualiasma ]
Salut,on peut implémenter des fonctions dans header par exemple calcul.h qui implémente les fonctions somme, multiplication. Dans mon programme main.c
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
MATRICE TEMPLATEMATRICE TEMPLATE par hjr2610
Cliquez pour lire la suite par hjr2610 RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|