// ONLY FOR UNIX SYSTEM!
// NOT FOR WINDOWS!
//
// this is the first version: 1.0
//
// Mind_Blog_ADMIN.c
//
// Copyright 2011 Francesco <pitagora@laptop>
// email <francescoleone.23@gmail.com>
// website <http://pitagora.hellospace.net>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301, USA.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#define FILE_PHP "index.php"
#define FILE_XML "data.xml"
#define MAX_BUF 500
#define VERO 1
#define FALSO 0
int port_store; /* usata per ricevere/inviare file */
int port_general = 21; /* port_general, usata per la connessione principale */
/* Principali :) */
void install(void); /* permette di installare il CMS */
void inet_nexus (struct sockaddr_in*, const in_addr_t, const int); /* permette di impostare i dati per la connessione */
void my_send (int, const char*, const char*); /* permette di inviare dati al server */
void my_recv (int, const int); /* permette di ricevere i dati dal server */
void format (char []); /* formatta il testo rivecuto dal server */
void store (const int, const char*); /* invia il file al server */
void update (FILE *, int, char [], char [], char [], struct tm*, char []); /* aggiorna il file xml con i nuovi dati */
/* Sotto - funzioni :) */
/* install --> */ void data_xml_func (FILE *); /* permette di creare il file data.xml */
/* install --> */ void index_php_func (FILE *); /* permette di salvare il file index.php */
/* add_new_article ---> */ void retrv (int, char[]); /* usata per il download dei file */
void add_new_article (void); /* aggiunge nuovi articoli al blog */
int main (void)
{
int scelta;
fprintf (stdout, "\t\tMind Blog - Admin\t\t\n\n");
fprintf (stdout, "1 = Installa Mind Blog sul tuo web!\n");
fprintf (stdout, "2 = Inserisci un nuovo articolo sul tuo Mind Blog!\n");
fprintf (stdout, "3 = Esci, semplicmente!\n");
fprintf (stdout, "? = ");
fscanf (stdin, "%d", &scelta);
switch (scelta) {
case 1: install (); break;
case 2: add_new_article (); break;
case 3: exit (EXIT_SUCCESS);
default: fprintf (stderr, "Errore nell'inserimento del numero!\n"); exit (EXIT_FAILURE);
}
return 0;
}
void install()
{
FILE *data_xml, *index_php; /* usati per gli stream dei due file necessari per il funzionamento del CMS */
char ip[20]; /* necessario per collegarsi all' FTP */
char username[20]; /* necessario per accedere all' FTP */
char password[20]; /* necessario per accedere all' FTP */
struct sockaddr_in info_general, info_store; /* struttura usata per impostare la connessione */
int sockfd_general, sockfd_store; /* stream socket */
/* creo ed apro i file */
index_php = fopen (FILE_PHP, "w");
data_xml = fopen (FILE_XML, "w");
/* se trovo qualche errore, avvisa ed esci */
if (index_php == NULL || data_xml == NULL) {
fprintf (stderr, "Errore nell'apertura del file!\n");
exit (EXIT_FAILURE);
}
/* scrivi nel file data.xml */
data_xml_func (data_xml);
/* scrivi nel file index.php */
index_php_func (index_php);
/* chiudi i file prcedentemente aperti */
fcloseall ();
printf ("Inserisci il tuo IP es: xx.xx.xx.xx : ");
scanf ("%s", ip);
printf ("Inserisci il tuo username: ");
scanf ("%s", username);
printf ("Inserici la tua password: ");
scanf ("%s", password);
/* imposto lo stream socket e controllo eventuali errori */
sockfd_general = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd_general < 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit(EXIT_FAILURE);
}
/* inizializzo la connessione */
inet_nexus (&info_general, inet_addr(ip), port_general);
/* mi connetto all'host e controllo se ci sono errori */
if ( (connect (sockfd_general, (struct sockaddr *) &info_general, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf (stderr, "Erorre nella connessione al server!\n" \
"Controlla se si ha impostato correttamente l'ip, l'username ed infine la password\n");
exit (EXIT_FAILURE);
}
/*invio dati */
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "USER", username);
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "PASS", password);
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "MKD", "blog");
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "CWD", "blog");
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "TYPE", "I");
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "PASV", "");
my_recv (sockfd_general, VERO);
/* connetto alla nuova porta, inizializzando i dati */
sockfd_store = socket (AF_INET , SOCK_STREAM, 0);
if (sockfd_store < 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit (EXIT_FAILURE);
}
inet_nexus (&info_store, inet_addr(ip), port_store);
if ( (connect (sockfd_store, (struct sockaddr *) &info_store, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf(stderr, "Errore nella connessione al server!\n");
exit (EXIT_FAILURE);
}
/* ora che è aperta una nuova connessione, posso inviare il file, non prima però di dirlo al server! */
fprintf (stdout, "\n[+] File creati con successo\n[+]Inizio ad inviare il file\n");
/* adesso, invia il file: DATA.XML */
my_send (sockfd_general, "STOR", FILE_XML);
my_recv (sockfd_general, FALSO);
store (sockfd_store, FILE_XML);
my_recv (sockfd_general, FALSO);
close (sockfd_store);
fprintf(stdout, "[+] %s spedito con successo\n[+]Inizio ad inviare il file\n", FILE_XML);
/* ripetiamo la stessa cosa con il file: INDEX.PHP */
my_send (sockfd_general, "PASV", "");
my_recv (sockfd_general, VERO);
/* connetto alla nuova porta, inizializzando i dati */
sockfd_store = socket (AF_INET , SOCK_STREAM, 0);
if (sockfd_store < 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit (EXIT_FAILURE);
}
inet_nexus (&info_store, inet_addr(ip), port_store);
if ( (connect (sockfd_store, (struct sockaddr *) &info_store, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf(stderr, "Errore nella connessione al server!\n");
exit (EXIT_FAILURE);
}
my_send (sockfd_general, "STOR", FILE_PHP);
my_recv (sockfd_general, FALSO);
store (sockfd_store, FILE_PHP);
my_recv (sockfd_general, FALSO);
close (sockfd_store);
fprintf(stdout, "[+] %s spedito con successo!\n", FILE_PHP);
/* esco dall'FTP e chiudo */
my_send (sockfd_general, "QUIT", "");
my_recv (sockfd_general, FALSO);
close (sockfd_general);
fprintf(stdout, "L'installazione e' avvenuta correttamente.\nGrazie per aver intallato, Mind Blog\n\nPitagora\n\nP.S. ");
fprintf(stdout, "Il tuo blog e' raggiungibile al tuo indirizzo aggiungendo un /blog\nes: www.pitagora.hellospace.net/blog\n");
remove(FILE_PHP);
remove(FILE_XML);
return;
}
void store (int sockfd, const char * nome_file)
{
int size;
char *buffer;
FILE *pag = fopen (nome_file, "r");
if (pag == NULL)
{
fprintf(stderr, "Errore, nell'aprire il file %s, Assicurati di non averlo cancellato o spostato." \
"Ri-avvia l'installazione\n", nome_file);
exit (EXIT_FAILURE);
}
/* ossento la dimensione del file */
fseek (pag, 0, SEEK_END);
size = ftell (pag);
rewind (pag);
buffer = calloc(1, sizeof (char) * (size + 1) ); /* alloco un buffer da contenere tutti i caratteri del file */
if (buffer == NULL)
{
fprintf(stderr, "Scusa, ma non puoi inserire più articoli, lo spazio e\' insufficiente\n");
exit (EXIT_FAILURE);
}
/* leggo il testo e lo invio */
fread (buffer, size, 1, pag);
write (sockfd, buffer, strlen (buffer) );
/* chiudo tutto */
free(buffer);
fclose (pag);
close (sockfd);
return;
}
void format (char testo[])
{
int p1, p2;
int virgole = 0;
char *frase;
frase = strtok (testo, ",)");
while (frase != NULL)
{
virgole += 1;
if (virgole == 5) {
p1 = atoi (frase);
break;
}
frase = strtok (NULL, ",)");
}
frase = strtok (NULL, ")");
p2 = atoi (frase);
port_store = p1*256+p2; /* assegno la nuova porta per il trasferimento dei file */
return;
}
void my_recv (int stream, const int bool)
{
char buffer[MAX_BUF];
/* azzero il buffer ad ogni chiamata */
memset (buffer, 0, MAX_BUF);
read (stream, buffer, MAX_BUF);
if (bool)
format (buffer);
return;
}
void my_send (int stream, const char* comando, const char* dato)
{
char buffer[MAX_BUF];
/* azzero il buffer ad ogni chiamata */
memset (buffer, 0, MAX_BUF);
/* l'invio deve essere così formattato: COMANDO dato \r\nSYST\r\n */
/* copio dentro buffer, prima il comando e poi aggiungo il dato, e poi \r\nSYST\r\n */
sprintf (buffer, "%s %s\r\n", comando, dato);
write (stream, buffer, strlen (buffer) );
return;
}
void inet_nexus (struct sockaddr_in *data, const in_addr_t ip, const int port)
{
data->sin_family = AF_INET;
data->sin_port = htons (port);
data->sin_addr.s_addr = (unsigned long) ip;
return;
}
void data_xml_func (FILE *database)
{
time_t raw_time; /* usata per prelevare l'ora */
struct tm *time_s; /* usata per poter stampare singoli pezzi della data */
time (&raw_time); /* prelevo il tempo */
time_s = localtime (&raw_time); /* prelevo la data */
fprintf (database, "<\?xml version=\"1.0\" encoding=\"utf-8\"\?>\n" \
"<!-- 1 -->\n" \
"<blog>\n"\
"\t<articolo id=\"1\">\n" \
"\t\t<titolo>Welcome to Mind blog</titolo>\n" \
"\t\t<testo>Grazie per aver installato Mind Blog.\n" \
"Grazie a Mind Blog, potrai gestire i tuoi dati, con totale sicurezza\n" \
"e senza l'ausilio di un database!\n"
"Per maggiori informazioni puoi contattare Pitagora all'indirizzo email: francescoleone.23@gmail.com\n" \
"P.S. Ricorda che Mind Blog - CMS e' un progetto open source. Per visionare il codice visita il forum.\n" \
"\t\t</testo>\n" \
"\t\t<autore>Pitagora</autore>\n" \
"\t\t<data>%d/%d/%d</data>\n" \
"\t</articolo>\n" \
"</blog>\n", time_s->tm_mday, (time_s->tm_mon + 1), (time_s->tm_year + 1900) );
return;
}
void index_php_func (FILE *index)
{
fprintf (index, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" \
"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" \
"<head>\n" \
"\t<title> Simple - Blog </title>\n" \
"\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>" \
"</head>\n" \
"<body>\n" \
"\t<p align=left>\n" \
"\t<font color=\"red\" size=\"10\"> Blog </font>" \
"\t</p>\n" \
"\t<\?php\n" \
"\t\t$xml = simplexml_load_file(\'data.xml\');\n" \
"\t\tforeach ( $xml->articolo as $articolo ) {\n" \
"\t\t\tprint \"<h1><center>\" . $articolo->titolo . \"</h1></center><br />\" .\n" \
"\t\t\t \"<p align=justify> <font color=\\\"black\\\" size=\\\"5\\\">\" . $articolo->testo . \"</font></p><br /><br />\" .\n" \
"\t\t\t \"<p align=right> <font color=\\\"grey\\\" size=\\\"6\\\">\" . $articolo->autore . \"-->\" . $articolo->data . \"</font></p><br /><br />\" .\n" \
"\t\t\t \"<hr /> <br />\";\n" \
"\t\t}\n" \
"\t\?>\n" \
"\t<font size=\"1\"><p><a href=\"http://mindblog.pitagora.hellospace.net\">Mind Blog - Pitagora</a></p></font>\n" \
"</body>\n");
return;
}
void add_new_article ()
{
char username[20], ip[20], password[20]; /* usati per connettersi al server */
char titolo[30], testo[BUFSIZ], autore[20]; /* usati per comporre il corpo del messaggio */
char corpo[BUFSIZ]; /* usata per concatenare: il titolo, il testo e l'autore */
char buffer[BUFSIZ];
time_t raw_time; /* usata per prelevare l'ora */
struct tm *time_s; /* usata per poter stampare singoli pezzi della data */
struct sockaddr_in info_general, info_store, info_retrv; /* per le connessioni */
int sockfd_general, sockfd_store, sockfd_retrv; /* stream associati alle connessioni */
FILE *xml; /* per aprire e scrivere nel file xml */
int elemento = 0; /* usato per inizializzare il nuovo articolo inserito nel xml */
printf ("Inserisci il tuo IP es: xx.xx.xx.xx : ");
scanf ("%s", ip);
printf ("Inserisci il tuo username: ");
scanf ("%s", username);
printf ("Inserici la tua password: ");
scanf ("%s", password);
/* imposto lo stream socket e controllo eventuali errori */
sockfd_general = socket (AF_INET, SOCK_STREAM, 0);
if (sockfd_general < 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit(EXIT_FAILURE);
}
/* inizializzo la connessione */
inet_nexus (&info_general, inet_addr(ip), port_general);
/* mi connetto all'host e controllo se ci sono errori */
if ( (connect (sockfd_general, (struct sockaddr *) &info_general, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf (stderr, "Erorre nella connessione al server!\n" \
"Controlla se si ha impostato correttamente l'ip, l'username ed infine la password\n");
exit (EXIT_FAILURE);
}
/*invio dati */
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "USER", username);
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "PASS", password);
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "CWD", "blog");
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "TYPE", "I");
my_recv (sockfd_general, FALSO);
my_send (sockfd_general, "PASV", "");
my_recv (sockfd_general, VERO);
/* mi connetto alla nuova porta per il download dei file */
sockfd_retrv = socket (AF_INET , SOCK_STREAM, 0);
if (sockfd_retrv< 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit (EXIT_FAILURE);
}
inet_nexus (&info_retrv, inet_addr(ip), port_store);
if ( (connect (sockfd_retrv, (struct sockaddr *) &info_retrv, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf(stderr, "Errore nella connessione al server!\n");
exit (EXIT_FAILURE);
}
my_send (sockfd_general, "RETR", FILE_XML);
my_recv (sockfd_general, FALSO);
retrv (sockfd_retrv, buffer);
my_recv (sockfd_general, FALSO);
close (sockfd_retrv);
/* ottieni il numero di articoli inseriti dentro il database flat */
sscanf (buffer, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- %d -->", &elemento);
/* incremento l'elemento */
++elemento;
while (getchar() != '\n'); /* svuoto il buffer */
fprintf (stdout, "Inserisci il titolo dell'articolo: ");
fgets (titolo, sizeof (titolo), stdin);
titolo[strlen (titolo) - 1] = '\0'; /* elimino il new-line */
fprintf (stdout, "Inserisci il testo dell'articolo. Per concludere premi invio:\n ");
fgets (testo, sizeof (testo), stdin);
testo[strlen (testo) - 1] = '\0';
fprintf (stdout, "Inserisci l'autore: ");
fgets (autore, sizeof (autore), stdin);
autore[strlen (autore) - 1] = '\0';
/* ottengo la data */
time (&raw_time);
time_s = localtime(&raw_time);
/* apro il file per inserire i dati aggiornati */
xml = fopen (FILE_XML, "w");
if (xml == NULL)
{
fprintf (stderr, "Errore nella creazione del file %s\n", FILE_XML);
exit (EXIT_FAILURE);
}
/* aggiorno il file aggiungendo il titolo il testo, l'autore, la data più il vecchio contenuto */
update (xml, elemento, titolo, testo, autore, time_s, buffer);
/* adesso devo rispedire il file */
my_send (sockfd_general, "PASV", "");
my_recv (sockfd_general, VERO);
/* connetto alla nuova porta, inizializzando i dati */
sockfd_store = socket (AF_INET , SOCK_STREAM, 0);
if (sockfd_store < 0)
{
fprintf (stderr, "Errore nella creazione del socket!\n");
exit (EXIT_FAILURE);
}
inet_nexus (&info_store, inet_addr(ip), port_store);
if ( (connect (sockfd_store, (struct sockaddr *) &info_store, sizeof (struct sockaddr_in) ) ) < 0)
{
fprintf(stderr, "Errore nella connessione al server!\n");
exit (EXIT_FAILURE);
}
fprintf (stdout, "Invio i dati\n");
my_send (sockfd_general, "STOR", FILE_XML);
my_recv (sockfd_general, FALSO);
store (sockfd_store, FILE_XML);
my_recv (sockfd_general, FALSO);
close (sockfd_store);
close (sockfd_general);
remove (FILE_XML);
fprintf(stdout, "Dati inviati con successo! Prova ad aggiornare la pagina.\n");
return;
}
void update (FILE *stream, int n, char title[], char text[], char author[], struct tm *time_s, char buffer[])
{
int contatore = 0;
/* scrive nel file i nuovi dati ... */
fprintf (stream, "<\?xml version=\"1.0\" encoding=\"utf-8\"\?>\n" \
"<!-- %d -->\n" \
"<blog>\n"\
"\t<articolo id=\"%d\">\n" \
"\t\t<titolo>%s</titolo>\n" \
"\t\t<testo>%s" \
"\t\t</testo>\n" \
"\t\t<autore>%s</autore>\n" \
"\t\t<data>%d/%d/%d</data>\n" \
"\t</articolo>\n", n, n, title, text, author, time_s->tm_mday, (time_s->tm_mon + 1), (time_s->tm_year + 1900) );
n = 0;
/* questo pasticcio mi permette di capire da dove devo iniziare a copiare */
while (1)
{
if (buffer[n] != '>')
{
n += 1;
} else {
n += 1;
contatore += 1;
if (contatore == 3)
{
break;
}
}
}
/* .. ed aggiunge quelli vecchi */
for (; buffer[n] != '\0'; n++)
{
fputc (buffer[n], stream);
}
fclose (stream);
return;
}
void retrv (int sockfd, char buffer[])
{
char buffer1[BUFSIZ];
memset (buffer1, 0, sizeof (buffer1) ); /* azzero i due buffer */
memset (buffer, 0, sizeof (buffer) );
/* finchè c'è qualche cosa da leggere leggi */
while (read (sockfd, buffer1, sizeof (buffer1) ) != 0) {
strncat (buffer, buffer1, strlen (buffer1) ); /* lo concatena al buffer */
memset (buffer1, 0, sizeof (buffer1) ); /* ri-azzera la memoria del buffer1 */
}
return;
}