PDA

View Full Version : [C++] Programma per filigrana pdf documents


giammi56
16-05-2010, 17:04
Salve a tutti,
Premetto di essere un quasi completo eretico della programmazione, ma mi è capitato un compito ingrato:
Per motivi di sicurezza mi sono ritrovato con la necessità di mettere la filigrana sui file .pdf che do ai miei studenti.. sono molti file e molti studenti e a mano mi è sembrato fin da subito proibitivo..
Ho così pensato di creare un programma che automatizzasse la cosa leggendo da un database i nomi.
Mi è stato consigliato di usare ImageMagick e di mettere i file in pdf.

Il codice che compila è questo:
E' stato scritto da Visual C++ 2010 Express su SO Win7 Ultimate.

/deve leggere una lista di nomi da un file .txt e tramite imagemagick che è una applicazione di image rendering, stampare su ogni pagina di alcuni documenti .pdf le immagini dei nomi letti come filigrana..


/* Lettura di un file riga per riga. */

/* (senza estensione e senza spazi) */



#define doc "cassino_alluminio"

// aggiunto questo

#include <string.h>

// fine

#include<stdlib.h>

#include<stdio.h>







int main()

{



FILE *fd;

fd = fopen ("nomi.txt" , "r");



char buf[50], imagemagick[300], imagemagick_2[300], dir[30];



char *res, *p;



/* apre il file dei nomi detto nomi.txt */



if( fd==NULL )

{

perror("Errore in apertura del file");



exit(1);

}





/* legge e stampa ogni riga del file nomi.txt */



while(1)

{

res=fgets(buf, 50, fd);



if( res==NULL )

break;



/* dichiaro directory imagemagick prima c'era mkdir */





// strcat va usato così !!!

strcat (dir, "mkdir");

strcat(imagemagick, "convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \'");



strcat(imagemagick_2 , "composite filigrana_");



system(dir);



system(imagemagick);



system(imagemagick_2);





printf("Fatto %s", buf);

}



/* chiude il file */



fclose(fd);



return 0;

}


Purtroppo non riesco a farlo andare come si deve perchè come vedrete facendolo girare mi dice:

|"A buffer overrun has occurred in Filigrana.exe which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program.

For more details please see Help topic 'How to debug Buffer Overrun Issues'."|

Qualcuno sa darmi una dritta?
Ringrazio per l'interessamento.

fero86
16-05-2010, 22:41
usa il tag CODE per scrivere codice nei post.

i buffer overrun di cui si lamenta il runtime sono dovuti al fatto che hai usato la strcat su dei vettori non inizializzati i quali non é detto che contengano uno zero come primo byte; la presenza dello zero come primo byte é necessaria a far si che inizialmente i buffers rappresentino stringhe vuote; mi spiego meglio, il problema é che non puoi passare stringhe non inizializzate alla strcat perché l'algoritmo della strcat consiste nel cercare la fine della stringa di destinazione e concatenarci l'altra stringa, ma le stringhe di destinazione che tu gli passi inizialmente non hanno potenzialmente fine perché la fine deve essere marcata da uno zero che tu non hai messo.

quindi per esempio subito prima di questa istruzione: strcat(dir, "mkdir"); dovresti mettere questa: dir[0] = 0;
che fa si che prima della catena di strcat il buffer dir contenga la stringa "".

comunque ti sconsiglio vivamente di usare il C, per quello che devi fare secondo me te la potresti cavare tranquillamente con uno script .js per WSH, oppure con PowerShell visto che usi Windows 7.

fero86
16-05-2010, 22:45
altra cosa, cambia il tag nel titolo della discussione: il programma che hai riportato non ha nulla a che vedere col C++, é scritto chiaramente in C :D

giammi56
17-05-2010, 00:59
Scusami.. Come avrai capito non me ne intendo un granché..
Purtroppo continua a dare lo stesso errore nonostante la modifica..
Se mi mettessi li con power shell secondo te riuscirei a trovare un modo per finire questa cosa?

Non c'è modo di intervenire su questo codice C?

Grazie

fero86
17-05-2010, 02:45
si che c'é modo, ovviamente in C é possibile scrivere un programma corretto e funzionante che faccia quello che vuoi fare. quello che dico io é che se devi imparare un linguaggio da zero per fare questa cosa, l'iniziativa é molto lodevole ma il C é sicuramente il punto di partenza sbagliato.

saró onesto, io purtroppo non ho mai avuto occasione di fare qualcosa di significativo con PowerShell e quindi non saprei aiutarti, ma me ne sono fatto un'infarinatura tempo addietro leggendomi della documentazione e sono sicuro che ti permetterá di fare quello che vuoi con molti meno grattacapi rispetto alla realizzazione di un programmetto in C. in ogni caso penso che in questa sezione ci sia gente piu esperta di me con PowerShell, quindi se cambi strada eventualmente potrai aprire una nuova discussione.

altrimenti se sei determinato col C posta l'ultima versione del sorgente usando il tag CODE :)

giammi56
17-05-2010, 16:58
Purtroppo ho i tempi stretti e credo che se riesco a capire dove mettere i file di imagemagick e come scrivere correttamente la funzione strcat potrei riuscire a tampnare il problema.. pOi potrei pensare all'ottimizzazione con powershell..
Ti ringrazio molto per la disponibilità e per il supporto!

//deve leggere una lista di nomi da un file .txt e tramite imagemagick che è una applicazione di image rendering, stampare su ogni pagina di alcuni documenti .pdf le immagini dei nomi letti come filigrana..

/* Lettura di un file riga per riga. */

/* (senza estensione e senza spazi) */

#define doc "cassino_alluminio"
#include <string.h>
#include<stdlib.h>
#include<stdio.h>



int main()
{

FILE *fd;
fd = fopen ("nomi.txt" , "r");

/*non legge gli spazi?*/

char buf[50], imagemagick[300], imagemagick_2[300], dir[30];

char *res, *p;

/* apre il file dei nomi detto nomi.txt */

if( fd==NULL )
{
perror("Errore in apertura del file");

exit(1);
}

/* legge e stampa ogni riga del file nomi.txt */

while(1)
{
res=fgets(buf, 50, fd);

if( res==NULL )
break;

/* dichiaro directory imagemagick prima c'era mkdir */

//dir = strcat ( "mkdir" , buf);

//imagemagick = strcat("convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \'",buf,"\'\" -channel RGBA -blur 0x6 -fill darkred - stroke magenta -draw \"text 20,55 \'",buf,"\'\" -channel Alpha -evaluate Divide 2 -trim +repage filigrana_",buf,".png");

// imagemagick_2 = strcat("composite filigrana_",buf,".png ", doc ,".pdf ",buf,"\\", doc ,".pdf");


dir[0] = 0;
strcat (dir, "mkdir");
strcat(imagemagick, "convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \'");
strcat(imagemagick, "convert -channel RGBA -blur 0x6 -fill darkred -stroke magenta -draw \"text 20,55 \'");
strcat(imagemagick, "convert -channel Alpha -evaluate Divide 2 -trim +repage filigrana_");
strcat(imagemagick, "convert .png");
strcat(imagemagick_2 , "composite cassino_alluminio.pdf");

system(dir);

system(imagemagick);

system(imagemagick_2);


printf("Fatto %s", buf);
}

/* chiude il file */

fclose(fd);

return 0;
}

Questa versione viene compilata senza problemi e mi genera il file .exe..
L'esecuzione del programma non da problemi nel senzo che si apre e si chiude la finestra della console..
Ho organizzato i file in questa maniera:
http://s6.imagestime.com/out.php/i468984_debug.jpg (http://www.imagestime.com/show.php/468984_debug.jpg.html)

Mi piacerebbe che rimanesse la finestra della console di windows una volta terminata l'esecuzione del programma..
Sospetto che non apra e non scriva sul file .pdf che ho impostato..
Come ho detto uso Visual C++ 2010 Express (la versione gratuita).
Grazie ancora per l'attenzione.

Kenger
17-05-2010, 17:31
Visto che tanto programmi su windows con visual C++ puoi mettere

system("pause");

poco prima del return.

EDIT: Ogni volta che fai strcat devi terminare la riga col separatore dei comandi di DOS(che non sò qual è). Al momento imagemagick è una cosa tipo:

convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \'convert -channel RGBA -blur 0x6 -fill darkred -stroke magenta -draw \"text 20,55 \'

tutto attaccato. Inoltre usi il comando mkdir senza dirgli il nome della directory da creare e quindi ti da errore subito.

EDIT2: I primi due comandi di imagemagick hanno del testo che inizia con \" e che viene terminato con \' al posto di \".

giammi56
26-05-2010, 16:58
Ciao,
Scusa per il delay ma non sono pià riuscito ad andare al computer.
Mi potresti dire come inserire la cartella da creare di mkdir?
Il comando pause non funziona messo lì (vedi codice)
Il separatore in dos è && . l'ho inserito nel codice qui sotto.
Il comando image magick fa quello che dovrebbe fare? Ho sostituito come vedi la formattazione \" con \' .
Secondo te si riesce a far partire questo benedetto?

Hai provato a farlo girare? crea delle cartelle dove c'è il file .pdf in questa maniera.. tutte vuote!

http://s6.imagestime.com/out.php/i470283_secondo.JPG (http://www.imagestime.com/show.php/470283_secondo.JPG.html)

//deve leggere una lista di nomi da un file .txt e tramite imagemagick che è una applicazione di image rendering, stampare su ogni pagina di alcuni documenti .pdf le immagini dei nomi letti come filigrana..

/* Lettura di un file riga per riga. */

/* (senza estensione e senza spazi) */

#define doc "cassino_alluminio"
#include<string.h>
#include<stdlib.h>
#include<stdio.h>



int main()
{

FILE *fd;
fd = fopen ("nomi.txt" , "r");

/*non legge gli spazi?*/

char buf[50], imagemagick[300], imagemagick_2[300], dir[30];

char *res, *p;

/* apre il file dei nomi detto nomi.txt */

if( fd==NULL )
{
perror("Errore in apertura del file");

exit(1);
}

/* legge e stampa ogni riga del file nomi.txt */

while(1)
{
res=fgets(buf, 50, fd);

if( res==NULL )
break;

/* dichiaro directory imagemagick prima c'era mkdir */

//dir = strcat ( "mkdir" , buf);

//imagemagick = strcat("convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \'",buf,"\'\" -channel RGBA -blur 0x6 -fill darkred - stroke magenta -draw \"text 20,55 \'",buf,"\'\" -channel Alpha -evaluate Divide 2 -trim +repage filigrana_",buf,".png");

// imagemagick_2 = strcat("composite filigrana_",buf,".png ", doc ,".pdf ",buf,"\\", doc ,".pdf");


dir[0] = 0;
strcat (dir, "mkdir (const char *cassino, mode_t mode");
strcat(imagemagick, "convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \" && -channel RGBA -blur 0x6 -fill darkred -stroke magenta -draw \"text 20,55 \" && -channel Alpha -evaluate Divide 2 -trim +repage filigrana_ && .png ");
strcat(imagemagick_2 , "composite filigrana_ && .png && .pdf && \\ && .pdf");

system(dir);

system(imagemagick);

system(imagemagick_2);


printf("Fatto %s", buf);
}

system("pause");

/* chiude il file */

fclose(fd);

return 0;

Kenger
26-05-2010, 23:00
Il comando mkdir (const char *cassino, mode_t mode cosa dovrebbe fare scusa?

Mentre questo
composite filigrana_ && .png && .pdf && \\ && .pdf
?

Visto che ci sei ti consiglio di fare stampare al programma anche il comando che esegue ogni volta facendo

printf("%s\n", dir);
printf("%s\n", imagemagick);
printf("%s\n", imagemagick_2);

così vedi cosa sta cercando di fare.

giammi56
27-05-2010, 13:40
nel mkdir dovrebbe creare una cartella con il nome dello studente di cui ha creato la filigrana e metterci dentro il file

la parte finale del codice di imagemagick dovrebbe apporre la filigrana .png al file .pdf .. o almeno credo!

Sono sbagliati?
Questo pomeriggio provo a vedere con i printf cosa fa il programma e posto l'output di console.

tomminno
27-05-2010, 13:48
nel mkdir dovrebbe creare una cartella con il nome dello studente di cui ha creato la filigrana e metterci dentro il file


Prova ad aprire la shell e digitare:

mkdir (const char *cassino, mode_t mode

Secondo te farà quello che hai appena detto?


la parte finale del codice di imagemagick dovrebbe apporre la filigrana .png al file .pdf .. o almeno credo!


imagemagick e imagemagick_2 dato che non li hai impostati a 0 potrebbero contenere chissà cosa.
E se anche li resettassi prima dell'uso se apri la solita shell e digiti:

convert -size 500x85 xc:transparent -font Arial -pointsize 68 -draw \"text 25,60 \" && -channel RGBA -blur 0x6 -fill darkred -stroke magenta -draw \"text 20,55 \" && -channel Alpha -evaluate Divide 2 -trim +repage filigrana_ && .png

e

composite filigrana_ && .png && .pdf && \\ && .pdf

Cosa ottieni? Secondo me una bella pernacchia :Prrr:


Sono sbagliati?


Decisamente.

giammi56
28-05-2010, 09:34
Come ho detto all'inizio non so praticamente nulla di programmazione e mi sono riferito ad un forum che reputo serio per avere, compatibilmente con tutto, un aiuto: non certo delle constatazioni di ignoranza veritiere ma sterili data la situazione.
Ti sarei molto più grato se mi suggerissi come organizzare le due variabili e come ritrovare il codice di imagemagick ch serve al mio scopo.

tomminno
28-05-2010, 11:27
Come ho detto all'inizio non so praticamente nulla di programmazione e mi sono riferito ad un forum che reputo serio per avere, compatibilmente con tutto, un aiuto: non certo delle constatazioni di ignoranza veritiere ma sterili data la situazione.
Ti sarei molto più grato se mi suggerissi come organizzare le due variabili e come ritrovare il codice di imagemagick ch serve al mio scopo.

Come usare imagemagick lo dovresti sapere te, eventualmente utilizzando la documentazione del programma. Google propone questa pagina: http://www.imagemagick.org/script/command-line-tools.php

Purtroppo senza conoscere i comandi corretti è difficile aiutarti.

Sei riuscito manualmente tramite linea di comando a fare quello che ti interessa anche solo in un caso?
Se si che comandi utilizzi?