Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Codificatore - cdf.cpp

cdf.cpp

Caricato da: AldoBaldo
Scarica il programma completo

  1. #include <limits.h>
  2. #include "cdf.h"
  3.  
  4.  
  5. // messaggi d'errore
  6. static const char *CDFStr_NoDati = "Dati insufficienti o inadatti.";
  7. static const char *CDFStr_NoMemoria = "Memoria insufficiente.";
  8. static const char *CDFStr_ChiaveNonValida = "Chiave non valida.";
  9. static const char *CDFStr_ChiaveNonDisponibile = "Chiave non disponibile.";
  10. static const char *CDFStr_DatiNonDisponibili = "Dati non disponibili.";
  11. static const char *CDFStr_PercorsoFileNonValido = "Percorso file non valido.";
  12. static const char *CDFStr_DatiNonSalvati = "Dati non salvati.";
  13.  
  14. // prototipi di funzioni non membro
  15. static int AccettaStringa( char **dest, const char *orig,
  16.     unsigned long *lDest, unsigned long lOrig = 0xFFFFFFFF );
  17. static char *DuplicaStringa( const char *s, unsigned long l = 0xFFFFFFFF );
  18. static void EliminaStringa( char **s, unsigned long *l );
  19. static void IdentificaCaratteri( char *sDati, unsigned long lDati, bool *lista );
  20. static unsigned long RandUl( unsigned long lim );
  21.  
  22.  
  23. CDF::CDF() {
  24.     InizializzaNullo();
  25. }
  26.  
  27.  
  28. CDF::CDF( const CDF& daCopiare ) {
  29.     if( !Copia(&daCopiare) ) throw CDFStr_NoMemoria;
  30. }
  31.  
  32.  
  33. CDF::~CDF() {
  34.     EliminaStringa( &chiave, &lChiave );
  35.     EliminaStringa( &dati, &lDati );
  36. }
  37.  
  38.  
  39. CDF& CDF::operator=(const CDF& daAssegnare) {
  40.     if (this == &daAssegnare) return *this; // gestisce l'auto assegnamento
  41.  
  42.     if( !Copia(&daAssegnare) ) throw CDFStr_NoMemoria;
  43.  
  44.     return *this;
  45. }
  46.  
  47.  
  48. void CDF::imposta_chiave( const char *sChiave, unsigned long l ) {
  49.     EliminaStringa( &chiave, &lChiave );
  50.  
  51.     switch( AccettaStringa(&chiave,sChiave,&lChiave,l) ) {
  52.         case 1: throw CDFStr_NoMemoria;
  53.         case 2: throw CDFStr_ChiaveNonDisponibile;
  54.         default: VerificaChiave(); break;
  55.     }
  56. }
  57.  
  58.  
  59. const char *CDF::ricava_chiave( void ) {
  60.     if( chiave != NULL )
  61.         return DuplicaStringa( chiave, lChiave );
  62.     else return chiave;
  63. }
  64.  
  65.  
  66. void CDF::imposta_dati( int tipoDati, const char *sDati, unsigned long l ) {
  67.     EliminaStringa( &dati, &lDati );
  68.  
  69.     ImpostaTipoDati( tipoDati );
  70.  
  71.     if( tDati == kCDFNoDati )
  72.         throw CDFStr_DatiNonDisponibili;
  73.  
  74.     switch( AccettaStringa(&dati,sDati,&lDati,l) ) {
  75.         case 1: throw CDFStr_NoMemoria;
  76.         case 2: throw CDFStr_DatiNonDisponibili;
  77.         default: VerificaChiave();
  78.     }
  79. }
  80.  
  81.  
  82. const char *CDF::ricava_dati( void ) {
  83.     if( dati != NULL )
  84.         return DuplicaStringa( dati, lDati );
  85.     else return dati;
  86. }
  87.  
  88.  
  89. void CDF::elabora( void ) {
  90.     switch( tDati ) {
  91.         case kCDFInChiaro: Codifica(); break;
  92.         case kCDFCodificati: Decodifica(); break;
  93.         default: throw CDFStr_DatiNonDisponibili;
  94.     }
  95. }
  96.  
  97.  
  98. void CDF::salva_dati( const char *percFile ) {
  99.     if( percFile == NULL ) throw CDFStr_PercorsoFileNonValido;
  100.     if( dati == NULL ) throw CDFStr_DatiNonDisponibili;
  101.  
  102.     FILE *f = fopen( percFile, "w+" );
  103.     if( f == NULL ) throw CDFStr_DatiNonSalvati;
  104.  
  105.     fprintf( f, dati );
  106.     fclose( f );
  107. }
  108.  
  109.  
  110. void CDF::InizializzaNullo( void ) {
  111.     chiave      = NULL;         // la stringa della chiave
  112.     lChiave     = 0;            // la quantita di caratteri nella chiave
  113.  
  114.     dati        = NULL;         // la stringa dei dati
  115.     lDati       = 0;            // la quantita di caratteri nei dati
  116.  
  117.     tDati       = kCDFNoDati;   // kCDFNoDati, kCDFInChiaro, kCDFCodificati
  118.  
  119.     InizializzaCaratteriMancanti();
  120. }
  121.  
  122.  
  123. bool CDF::Copia( const CDF *originale ) {
  124.     try {
  125.         chiave = dati = NULL;
  126.  
  127.         lChiave = originale->lChiave;
  128.         chiave = new char[lChiave+1];
  129.         memcpy( chiave, originale->chiave, lChiave+1 );
  130.  
  131.         lDati = originale->lDati;
  132.         dati = new char[lDati+1];
  133.         memcpy( dati, originale->dati, lDati+1 );
  134.  
  135.         tDati = originale->tDati;
  136.  
  137.         for( int i=0; i<256; ++i )
  138.             carMancanti[i] = originale->carMancanti[i];
  139.         nCarMancanti = originale->nCarMancanti;
  140.  
  141.         return true;
  142.     } catch( ... ) {
  143.         delete[] chiave;
  144.         delete[] dati;
  145.         return false;
  146.     }
  147. }
  148.  
  149.  
  150. void CDF::InizializzaCaratteriMancanti( void ) {
  151.     for( nCarMancanti=256; nCarMancanti; ) // la quantita dei caratteri mancanti
  152.         carMancanti[--nCarMancanti] = '\0'; // i caratteri mancanti nella chiave
  153. }
  154.  
  155.  
  156. void CDF::ImpostaTipoDati( int tipoDati ) {
  157.     switch( tipoDati ) {
  158.         case kCDFInChiaro:
  159.         case kCDFCodificati:
  160.             tDati = tipoDati;
  161.             break;
  162.         default:
  163.             tDati = kCDFNoDati;
  164.     }
  165. }
  166.  
  167.  
  168. bool CDF::VerificaChiave( void ) {
  169.     unsigned long i;
  170.     bool carInChiaro[256];
  171.     bool carInChiave[256];
  172.  
  173.     InizializzaCaratteriMancanti();
  174.     if( chiave == NULL ) return false;
  175.     if( dati == NULL ) return true;
  176.     if( tDati == kCDFCodificati ) return true;
  177.  
  178.     // identificazione dei caratteri presenti nel testo in chiaro
  179.     IdentificaCaratteri( dati, lDati, carInChiaro );
  180.  
  181.     // identificazione dei caratteri presenti nella chiave
  182.     IdentificaCaratteri( chiave, lChiave, carInChiave );
  183.  
  184.     // conteggio e memorizzazione dei caratteri mancanti
  185.     for( nCarMancanti=0, i=0; i<256; ++i )
  186.         if(carInChiaro[i] && !carInChiave[i])
  187.             carMancanti[nCarMancanti++] = i;
  188.  
  189.     return ( nCarMancanti == 0 );
  190. }
  191.  
  192.  
  193. void CDF::Codifica( void ) {
  194.     if( chiave==NULL || dati==NULL || nCarMancanti!=0 ) throw CDFStr_NoDati;
  195.  
  196.     char *buff = NULL;
  197.     char *pBuff = NULL;
  198.     char cifre[16];
  199.     int maxCifre;
  200.     unsigned long i, j;
  201.     char sep[] = { '8', '9' };
  202.     char a, b;
  203.  
  204.     // rileva la quantita' massima delle cifre che possono costituire ciascuno
  205.     // degli indici che verranno memorizzati nella versione codificata del testo
  206.     sprintf( cifre, "%lo", lChiave );
  207.     maxCifre = strlen( cifre );
  208.  
  209.         try { // alloca un buffer temporaneo per il testo codificato
  210.         buff = new char[lDati*(maxCifre+1)+1];
  211.         // un unsigned long ottale convertito in stringa conta un massimo
  212.         // di 11 caratteri; e' stato usato 12 per far spazio al separatore;
  213.         // "+1" invece occorre per prevedere spazio per il terminatore
  214.         pBuff = buff;
  215.         } catch( ... ) {
  216.             throw CDFStr_NoMemoria;
  217.         }
  218.  
  219.     // Carattere per carattere, scorre il testo in chiaro. Per ogni carattere
  220.     // cerca un corrispondente nel file della chiave partendo da un punto casua-
  221.     // le. Quando lo trova, ne memorizza la posizione sotto forma di un numero
  222.     // in formato ottale. Le posizioni sono separate tra loro da un '8' o da un
  223.     // '9' (anche questo separatore e' scelto in modo casuale).
  224.  
  225.     for( i=0; i<lDati; i++ ) {
  226.         j = RandUl( lChiave );
  227.         a = dati[i];
  228.  
  229.         do {
  230.             b = chiave[j];
  231.  
  232.             if( a == b ) {
  233.                 if(i != lDati-1 ) {
  234.                     pBuff += sprintf( pBuff, "%lo%c", j, sep[rand()%2] );
  235.                 }
  236.                 else {
  237.                     // se siamo all'ultimo carattere, il
  238.                     // separatore puo' essere o non essere aggiunto
  239.                     if( rand()%5)
  240.                         pBuff += sprintf( pBuff, "%lo", j );
  241.                     else pBuff += sprintf( pBuff, "%lo%c", j, sep[rand()%2] );
  242.                 }
  243.             }
  244.  
  245.             ++j;
  246.             if( j >= lChiave ) j = 0;
  247.         } while( a != b );
  248.     }
  249.  
  250.     if( RinnovaDati(buff,pBuff-buff) ) {
  251.         delete[] buff;
  252.         tDati = kCDFCodificati;
  253.     }
  254.     else {
  255.         delete[] buff;
  256.         throw CDFStr_NoMemoria;
  257.     }
  258. }
  259.  
  260.  
  261. void CDF::Decodifica( void ) {
  262.     if( chiave==NULL || dati==NULL || nCarMancanti!=0 ) throw CDFStr_NoDati;
  263.  
  264.     char *buff = NULL;
  265.     char *pBuff = NULL;
  266.     unsigned long pos;
  267.     char *p, *b;
  268.     char ottale[16];
  269.     char aux, prec;
  270.  
  271.     try { // alloca un buffer temporaneo per il testo decodificato
  272.         buff = new char[lDati+1];
  273.         // i dati decodificati hanno sempre dimensioni minori rispetto ai dati
  274.         // codificati; "+1" occorre per prevedere spazio per il terminatore
  275.         pBuff = buff;
  276.         } catch( ... ) {
  277.             throw CDFStr_NoMemoria;
  278.         }
  279.  
  280.     // Scorre il file codificato cercando i separatori '8' e '9' per isolare i
  281.     // singoli numeri ottali che indicano le posizioni dei caratteri nella chia-
  282.     // ve. Legge quei numeri e ricompone il testo in chiaro nel file temporaneo.
  283.  
  284.     p = dati;
  285.     b = ottale;
  286.     prec = -1;
  287.  
  288.     do {
  289.         aux = *p;
  290.  
  291.         if( aux != '8' && aux != '9' && aux != '\0' ) {
  292.             *b = aux;
  293.             ++b;
  294.             ++p;
  295.         }
  296.         else {
  297.             if( aux == '\0' && (prec=='8'||prec=='9')) break;
  298.             *b = '\0';
  299.             sscanf( ottale, "%lo", &pos );
  300.  
  301.             if( pos>=lChiave ) {
  302.                 delete[] buff;
  303.                 throw CDFStr_ChiaveNonValida;
  304.             }
  305.  
  306.             pBuff += sprintf( pBuff, "%c", chiave[pos] );
  307.             if( aux == '\0' ) break;
  308.             b = ottale;
  309.             ++p;
  310.         }
  311.  
  312.         prec = aux;
  313.     } while( true );
  314.  
  315.     if( RinnovaDati(buff,pBuff-buff) ) {
  316.         delete[] buff;
  317.         tDati = kCDFInChiaro;
  318.     }
  319.     else {
  320.         delete[] buff;
  321.         throw CDFStr_NoMemoria;
  322.     }
  323. }
  324.  
  325.  
  326. bool CDF::RinnovaDati( char *nuoviDati, unsigned long l ) {
  327.     if( nuoviDati == NULL ) return false;
  328.  
  329.     EliminaStringa( &dati, &lDati );
  330.     tDati = kCDFNoDati;
  331.  
  332.     try {
  333.         dati = new char[l+1];
  334.         memcpy( dati, nuoviDati, l+1 );
  335.         lDati = l;
  336.         return true;
  337.     } catch( ... ) {
  338.         return false;
  339.     }
  340. }
  341.  
  342.  
  343. int AccettaStringa( char **dest, const char *orig,
  344.                     unsigned long *lDest, unsigned long lOrig ) {
  345.     if( orig != NULL ) {
  346.         if( lOrig == 0xFFFFFFFF ) lOrig = strlen( orig );
  347.         *dest = DuplicaStringa( orig, lOrig );
  348.         *lDest = *dest!=NULL ? lOrig : 0;
  349.         if( *dest != NULL ) return 0; else return 1;
  350.     }
  351.     else {
  352.         return 2;
  353.     }
  354. }
  355.  
  356.  
  357. char *DuplicaStringa( const char *s, unsigned long l ) {
  358.     if( l==0xFFFFFFFF ) l = strlen( s );
  359.  
  360.     try {
  361.         char *esito = new char[l+1];
  362.         strcpy( esito, s );
  363.         return esito;
  364.     } catch( ... ) {
  365.         return NULL;
  366.     }
  367. }
  368.  
  369.  
  370. void EliminaStringa( char **s, unsigned long *l ) {
  371.     delete[] *s;
  372.     *s = NULL;
  373.     *l = 0;
  374. }
  375.  
  376.  
  377.  
  378. void IdentificaCaratteri( char *sDati, unsigned long lDati, bool *lista ) {
  379.     unsigned long i;
  380.  
  381.     for( i=0; i<256; ++i ) lista[i] = false;
  382.  
  383.     if( sDati == NULL ) return;
  384.  
  385.     for( i=0; i<lDati; ++i ) {
  386.         if( sDati[i]>='\0')
  387.             lista[(int)sDati[i]] = true;
  388.         else lista[(int)sDati[i]+256] = true;
  389.     }
  390. }
  391.  
  392.  
  393. unsigned long RandUl( unsigned long lim ) {
  394.     return ((((unsigned long)rand())<<17)+(((unsigned long)rand())<<2)+rand()%4)%lim;
  395. }