///////////////////////////////////////////////////////////////////////////// // Rev 11/12/2003 // // // UNCHUNK.C // --------- // // // Sylvain MARECHAL - sylvain.marechal1@libertysurf.fr ///////////////////////////////////////////////////////////////////////////// // // Permet de "dechunker" un fichier // Les chunks sont un mode de transfert de donnees de HTTP 1.1. Leur but est // que la connexion TCP/IP reste ouverte, meme lorsqu'on ne connait pas la // taille de l'entite a transmettre. Dans ce cas, le serveur indique dans // l'entete HTTP "Transfert-Encoding: Chunked", puis prefixe chaque paquet // de donnees de sa taille, la fin etant signalee par un chunk de taille 0 // // Voir la RFC 2616 pour plus de details ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include /************************************************************/ int Char4BitsToInt( char cInt ) { if(cInt >= '0' && cInt <= '9' ) return cInt - '0'; if( cInt == 'A' || cInt == 'B' || cInt == 'C' || cInt == 'D' || cInt == 'E' || cInt == 'F' ) return cInt - 'A' + 10; if( cInt == 'a' || cInt == 'b' || cInt == 'c' || cInt == 'd' || cInt == 'e' || cInt == 'f' ) return cInt - 'a' + 10; return 0; } /************************************************************/ int CharHexToInt( char * szInt, int cb ) { int nResult = 0, cbTot = cb; while( cb ) { nResult += Char4BitsToInt( szInt[cbTot - cb] ) << (( cb - 1)*4); cb --; } return nResult; } /************************************************************/ void main( int argc, char * argv[] ) { int hFile = -1; char * pBuffer = NULL; int cbBuffer = 0; int hCreat = -1; char * p; int cbChunk; int nChunks = 0; int cbWritten = 0; int fSuppressHttpHeader = FALSE; if( argc < 3 ) { printf( "Usage %s [Suppress HTTP Header]\n", argv[0] ); exit(0); } if( argc == 4 ) { fSuppressHttpHeader = TRUE; } // Open file hFile = open( argv[1], O_BINARY | O_RDONLY ); if( hFile == -1 ) { printf( "open() error %d\n", errno ); getch(); exit(1); } hCreat = creat( argv[2], 644 ); if( hCreat == -1 ) { printf( "open() error %d\n", errno ); getch(); exit(1); } #ifdef _WIN32 setmode( hCreat, O_BINARY ); #endif // Get size cbBuffer = lseek( hFile, 0, SEEK_END ); lseek( hFile, 0, SEEK_SET ); // Alloc buffer pBuffer = (char *)malloc( cbBuffer ); if( pBuffer == NULL ) { close( hFile ); printf( "Memory allocation error\n" ); exit(1); } // Read data into buffer if( read( hFile, pBuffer, cbBuffer ) != cbBuffer ) { printf( "read() error %d\n", errno ); free( pBuffer ); close( hFile ); exit(1); } close( hFile ); if( fSuppressHttpHeader ) { p = strstr( pBuffer, "\r\n\r\n" ); if( ! p ) { p = strstr( pBuffer, "\n\n" ); } else { p += 4; } if( ! p ) { p = pBuffer; printf( "HTTP Header not found\n" ); } else { p += 2; } } else { p = pBuffer; } // Write chunks into file do { //static int PrintOne = 1; char * p2; p2 = strstr( p, "\r\n" ); if( ! p2 ) { printf( "Chunk not found at pos %d (file size is %d)\n", p - pBuffer, cbBuffer ); close( hCreat ); exit(1); } cbChunk = CharHexToInt( p, p2-p ); nChunks ++; if( cbBuffer < cbWritten + cbChunk ) { printf( "File not complete (file size is %d)\n", cbBuffer ); cbWritten += write( hCreat, p2 + 2, cbBuffer - cbWritten ); close( hCreat ); exit(1); } cbWritten += write( hCreat, p2 + 2, cbChunk ); p = p2 + 2 + cbChunk + 2; } while( (cbChunk > 0) || ( p - pBuffer < cbBuffer ) ); close( hFile ); printf( "File has %d chunks\n", nChunks ); // Make JL happy :-) free( pBuffer ); }