/* RESPONSE_error( HTTP_SESSION *http_session, const char *http_status_code, const char *http_error_message, const char* add_headers ) @http_session - wska�nik do pod��czonego klienta @http_status_code - kod b��du @http_error_message - tre�� b��du, kt�ra wy�wietli si� w przegl�darce @add_headers - dodatkowe nag��wki ( ustawione w funkcji wywo�uj�cej i przekazane przez ten parametr - funkcja wysy�a do przegl�darki ( klienta ) informacj� o b��dzie, kt�ry wyst�pi� na skutek ��dania */ void RESPONSE_error( HTTP_SESSION *http_session, const char *http_status_code, const char *http_error_message, const char* add_headers ) { char *http_header_to_send; char *http_single_header_line; int len = 0; /* Alokacja pami�ci */ http_header_to_send = malloc( MAX_BUFFER_CHAR+1 ); mem_allocated( http_header_to_send, 30 ); http_single_header_line = malloc( STD_BUFF_SIZE_CHAR ); mem_allocated( http_single_header_line, 31 ); /* HTTP/1.X XXX OPIS */ sprintf( http_single_header_line, "%s %s\r\n", HTTP_VER, http_status_code ); strncpy( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Server: */ sprintf( http_single_header_line, "%s\r\n", HEADER_SERVER ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Connection: Keep-Alive */ if( http_session->http_info.keep_alive ) { sprintf( http_single_header_line, "%s%s\r\n", HEADER_CONNECTION, HEADER_KEEP_ALIVE_STR ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); } /* Accept Ranges: bytes */ strncat( http_header_to_send, HEADER_ACCEPT_RANGES, MAX_BUFFER ); /* Dodatkowe nag��wki */ if( add_headers ) { strncat( http_header_to_send, add_headers, MAX_BUFFER ); } /* Content-Length */ len = strlen( http_error_message ); sprintf( http_single_header_line, "%s%d\r\n", HEADER_CONTENT_LENGTH, len ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Pusta linia */ strncat( http_header_to_send, "\r\n", MAX_BUFFER ); /* Wysy�ka nag��wka HTTP */ SESSION_send_response( http_session, http_header_to_send, strlen( http_header_to_send ) ); /* Wysy�ka tre�ci b��du, je�eli istnieje */ if( http_error_message ) { SESSION_send_response( http_session, http_error_message, len ); } /* Zapis ��dania do logu */ LOG_print( "%s %s %s \"%s\" %s %.3s\n", get_actual_time_gmt(), http_session->http_info.remote_addr, http_method_list[ http_session->http_info.method_name ], http_session->http_info.http_local_path, http_session->http_info.protocol_ver, http_status_code ); /* Zwolnienie pami�ci */ free( http_header_to_send ); http_header_to_send = NULL; free( http_single_header_line ); http_single_header_line = NULL; }
void CodeTable::update() { if (in_update++) { in_update--; return; } int part = 100 * makes / total_nodes; long mem = (mem_allocated()+1048575)/1048576; if (options.statistics || options.intermediate) cout << part << "% completed (" << dfa_in_mem+gta_in_mem << " automata in memory, " << mem << "MB memory used)\n"; else { cout << "\r "; cout << "\r" << part << "% completed"; if (part == 100) cout << " \n" << "Space: " << mem << "MB\n"; else cout << " (" << dfa_in_mem+gta_in_mem << " automata in memory, " << mem << "MB memory used)"; } flush(cout); if (part<100) in_update--; }
/* file_params( const char *filename ) @filename - nazwa pliku ( +�cie�ka ) - sprawdza, czy podany w zmiennej filename plik istnieje - pr�buje otworzy� plik - zwraca int, gdzie: + 0 = nie istnieje + 1 = istnieje, jest do odczytu, nie wymaga autentykacji + 2 = istnieje, brak uprawnie� do odczytu + 3 = istnieje, wymagana autentykacja */ short file_params( HTTP_SESSION *http_session, const char *filename, char *ht_access_pwd ) { FILE *resource; struct stat file_stat; int tmp_socket; int i = 0; /* Weryfikacja, czy podany parametr jest prawid�ow� nazw� pliku */ stat( filename, &file_stat ); if( file_stat.st_mode & S_IFREG ); else {/* Nie jest... */ return 0; } tmp_socket = ( http_session ? http_session->socket_descriptor : -133 ); /*Sprawdza, czy uda�o si� otworzy� plik */ resource = battery_fopen( filename, READ_BINARY, 1, tmp_socket, STD_FILE ); if( !resource ) { return 0; } else { if( http_session == NULL ) { return 1; } /* Pobranie informacji o ostatniej dacie modyfikacji zasobu */ if( !http_session->local_info.date_res_last_modified ) { http_session->local_info.date_res_last_modified = malloc( TIME_BUFF_SIZE_CHAR ); mem_allocated( http_session->local_info.date_res_last_modified, 20 ); } strftime( http_session->local_info.date_res_last_modified, TIME_BUFF_SIZE, RFC1123FMT, gmtime( &file_stat.st_mtime ) ); /* Sprawdza, czy plik ma uprawnienia do odczytu */ if( file_stat.st_mode & S_IREAD ) { if( ht_access_pwd && ht_access_count > 0 ) { for( i = 0; i < ht_access_count; i++ ) { if( strncmp( ht_access[ i ].res_filename, filename, MAX_PATH_LENGTH ) == 0 ) { /* Zas�b wymaga autoryzacji */ strncpy( ht_access_pwd, ht_access[ i ].res_auth, STD_BUFF_SIZE ); return 3; } } } } else { /* Nie ma */ return 2; } } return 1; }
/* basic sequential allocation of single byte blocks */ int test_alloc_1(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes = 0; int correct_alloc = 100; int correct_largest_free = 0; int i; void* lastPointer = NULL; initmem(strategy,100); for (i = 0; i < 100; i++) { void* pointer = mymalloc(1); if ( i > 0 && pointer != (lastPointer+1) ) { printf("Allocation with %s was not sequential at %i; expected %p, actual %p\n", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } if (mem_holes() != correct_holes) { printf("Holes not counted as %d with %s\n", correct_holes, strategy_name(strategy)); return 1; } if (mem_allocated() != correct_alloc) { printf("Allocated memory not reported as %d with %s\n", correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free not reported as %d with %s\n", correct_largest_free, strategy_name(strategy)); return 1; } } return 0; }
/* SOCKET_process( int socket_fd ) @socket_fd - identyfikator gniazda - funkcja odczytuje dane z gniazda */ static void SOCKET_process( int socket_fd ) { HTTP_SESSION *session = ( HTTP_SESSION* )malloc( sizeof( HTTP_SESSION ) ); char tmp_buf[ MAX_BUFFER ]; extern int errno; errno = 0; session->http_info.received_all = http_session_.http_info.received_all; session->address = http_session_.address; session->socket_descriptor = socket_fd; session->address_length = recv( ( int )socket_fd, tmp_buf, MAX_BUFFER, 0 ); if( session->address_length < MAX_URI_LENGTH ) { if( errno > 1) { SESSION_delete_send_struct( socket_fd ); SOCKET_close( socket_fd ); } else { if ( session->address_length <= 0 ) { /* ...ale to jednak by�o roz��czenie */ SESSION_delete_send_struct( socket_fd ); SOCKET_close( socket_fd ); } else if (session->address_length > 0 ) { /* Nie zosta�y wcze�niej odebrane wszystkie dane - metoda POST. Teraz trzeba je doklei� do http_info.content_data */ if( session->http_info.received_all == 0 ) { /* Obiekt jest ju� stworzony, nie trzeba przydziela� pami�ci */ session->http_info.content_data = ( char* )realloc( session->http_info.content_data, strlen( session->http_info.content_data )+session->address_length+1 ); strncat( session->http_info.content_data, tmp_buf, session->address_length ); session->http_info.received_all = 1; } else if( session->http_info.received_all == -1 ) { /* Dla metod GET i HEAD */ session->http_info.content_data = malloc( (session->address_length+1)*sizeof( char ) ); mem_allocated( session->http_info.content_data, 25 ); strncpy( session->http_info.content_data, tmp_buf, session->address_length ); } /* "Przerobienie" zapytania */ SESSION_prepare( session ); } } } else { RESPONSE_error( session, HTTP_414_REQUEST_URI_TOO_LONG, HTTP_ERR_414_MSG, NULL ); SOCKET_disconnect_client( session ); SESSION_release( session ); } if( session ) { free( session ); session = NULL; } }
/* basic sequential allocation followed by 50 frees */ int test_alloc_3(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes = 50; int correct_alloc = 50; int correct_largest_free = 1; int i; void* lastPointer = NULL; initmem(strategy,100); for (i = 0; i < 100; i++) { void* pointer = mymalloc(1); if ( i > 0 && pointer != (lastPointer+1) ) { printf("Allocation with %s was not sequential at %i; expected %p, actual %p\n", strategy_name(strategy), i,lastPointer+1,pointer); return 1; } lastPointer = pointer; } for (i = 1; i < 100; i+= 2) { myfree(mem_pool() + i); } if (mem_holes() != correct_holes) { printf("Holes not counted as %d with %s\n", correct_holes, strategy_name(strategy)); return 1; } if (mem_allocated() != correct_alloc) { printf("Memory not reported as %d with %s\n", correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free not reported as %d with %s\n", correct_largest_free, strategy_name(strategy)); return 1; } for(i=0;i<100;i++) { if(mem_is_alloc(mem_pool()+i) == i%2) { printf("Byte %d in memory claims to ",i); if(i%2) printf("not "); printf("be allocated. It should "); if(!i%2) printf("not "); printf("be allocated.\n"); return 1; } } } return 0; }
/* performs a randomized test: totalSize == the total size of the memory pool, as passed to initmem2 totalSize must be less than 10,000 * minBlockSize fillRatio == when the allocated memory is >= fillRatio * totalSize, a block is freed; otherwise, a new block is allocated. If a block cannot be allocated, this is tallied and a random block is freed immediately thereafter in the next iteration minBlockSize, maxBlockSize == size for allocated blocks is picked uniformly at random between these two numbers, inclusive */ void do_randomized_test(int strategyToUse, int totalSize, float fillRatio, int minBlockSize, int maxBlockSize, int iterations) { void * pointers[10000]; int storedPointers = 0; int strategy; int lbound = 1; int ubound = 4; int smallBlockSize = maxBlockSize/10; if (strategyToUse>0) lbound=ubound=strategyToUse; FILE *log; log = fopen("tests.log","a"); if(log == NULL) { perror("Can't append to log file.\n"); return; } fprintf(log,"Running randomized tests: pool size == %d, fill ratio == %f, block size is from %d to %d, %d iterations\n",totalSize,fillRatio,minBlockSize,maxBlockSize,iterations); fclose(log); for (strategy = lbound; strategy <= ubound; strategy++) { double sum_largest_free = 0; double sum_hole_size = 0; double sum_allocated = 0; int failed_allocations = 0; double sum_small = 0; struct timespec execstart, execend; int force_free = 0; int i; storedPointers = 0; initmem(strategy,totalSize); #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); execstart.tv_sec = mts.tv_sec; execstart.tv_nsec = mts.tv_nsec; #else clock_gettime(CLOCK_REALTIME, &execstart); #endif for (i = 0; i < iterations; i++) { if ( (i % 10000)==0 ) srand ( time(NULL) ); if (!force_free && (mem_free() > (totalSize * (1-fillRatio)))) { int newBlockSize = (rand()%(maxBlockSize-minBlockSize+1))+minBlockSize; /* allocate */ void * pointer = mymalloc(newBlockSize); if (pointer != NULL) pointers[storedPointers++] = pointer; else { failed_allocations++; force_free = 1; } } else { int chosen; void * pointer; /* free */ force_free = 0; if (storedPointers == 0) continue; chosen = rand() % storedPointers; pointer = pointers[chosen]; pointers[chosen] = pointers[storedPointers-1]; storedPointers--; myfree(pointer); } sum_largest_free += mem_largest_free(); sum_hole_size += (mem_free() / mem_holes()); sum_allocated += mem_allocated(); sum_small += mem_small_free(smallBlockSize); } #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time //clock_serv_t cclock; //mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); execend.tv_sec = mts.tv_sec; execend.tv_nsec = mts.tv_nsec; #else clock_gettime(CLOCK_REALTIME, &execend); #endif log = fopen("tests.log","a"); if(log == NULL) { perror("Can't append to log file.\n"); return; } fprintf(log,"\t=== %s ===\n",strategy_name(strategy)); fprintf(log,"\tTest took %.2fms.\n", (execend.tv_sec - execstart.tv_sec) * 1000 + (execend.tv_nsec - execstart.tv_nsec) / 1000000.0); fprintf(log,"\tAverage hole size: %f\n",sum_hole_size/iterations); fprintf(log,"\tAverage largest free block: %f\n",sum_largest_free/iterations); fprintf(log,"\tAverage allocated bytes: %f\n",sum_allocated/iterations); fprintf(log,"\tAverage number of small blocks: %f\n",sum_small/iterations); fprintf(log,"\tFailed allocations: %d\n",failed_allocations); fclose(log); } }
/* alloc, alloc, free, alloc */ int test_alloc_2(int argc, char **argv) { strategies strategy; int lbound = 1; int ubound = 4; if (strategyFromString(*(argv+1))>0) lbound=ubound=strategyFromString(*(argv+1)); for (strategy = lbound; strategy <= ubound; strategy++) { int correct_holes; int correct_alloc; int correct_largest_free; int correct_small; void* first; void* second; void* third; int correctThird; initmem(strategy,100); first = mymalloc(10); second = mymalloc(1); myfree(first); third = mymalloc(1); if (second != (first+10)) { printf("Second allocation failed; allocated at incorrect offset with strategy %s", strategy_name(strategy)); return 1; } correct_alloc = 2; correct_small = (strategy == First || strategy == Best); switch (strategy) { case Best: correctThird = (third == first); correct_holes = 2; correct_largest_free = 89; break; case Worst: correctThird = (third == second+1); correct_holes = 2; correct_largest_free = 88; break; case First: correctThird = (third == first); correct_holes = 2; correct_largest_free = 89; break; case Next: correctThird = (third == second+1); correct_holes = 2; correct_largest_free = 88; break; case NotSet: break; } if (!correctThird) { printf("Third allocation failed; allocated at incorrect offset with %s", strategy_name(strategy)); return 1; } if (mem_holes() != correct_holes) { printf("Holes counted as %d, should be %d with %s\n", mem_holes(), correct_holes, strategy_name(strategy)); return 1; } if (mem_small_free(9) != correct_small) { printf("Small holes counted as %d, should be %d with %s\n", mem_small_free(9), correct_small, strategy_name(strategy)); return 1; } if (mem_allocated() != correct_alloc) { printf("Memory reported as %d, should be %d with %s\n", mem_allocated(0), correct_alloc, strategy_name(strategy)); return 1; } if (mem_largest_free() != correct_largest_free) { printf("Largest memory block free reported as %d, should be %d with %s\n", mem_largest_free(), correct_largest_free, strategy_name(strategy)); return 1; } } return 0; }
/* REQUEST_get_range( HTTP_SESSION *http_session, int type ) @http_session - wska�nik do pod��czonego klienta @type - okre�la, czy funkcja ma pobra� i zwr�ci� pocz�tkowy lub ko�cowy zakres z nag��wka "Range" - zwraca liczb� bajt�w ( pocz�tkowych lub ko�cowych ) dla ��dania fragmentu zasobu */ long REQUEST_get_range( HTTP_SESSION *http_session, int type ) { char *range; char *temp_r; char *ptr; long range_s = -1; int i = 0; int len = 0; /* Pobranie warto�ci nag��wka "Range" do zmiennej tymczasowej */ ptr = malloc( STD_BUFF_SIZE_CHAR ); strncpy( ptr, REQUEST_get_header_value( http_session->http_info.header, HEADER_RANGE ), STD_BUFF_SIZE ); if( strlen( ptr ) == 0 ) { /* Nag�owek nie istnieje */ free( ptr ); ptr = NULL; return ( -1 ); } /* Rezerwacja pami�ci */ range = malloc( SMALL_BUFF_SIZE_CHAR ); mem_allocated( range, 36 ); temp_r = malloc( SMALL_BUFF_SIZE_CHAR ); mem_allocated( temp_r, 37 ); /* Przypisanie do zmiennej range warto�ci zmiennej tymczasowej */ strncpy( range, ptr, SMALL_BUFF_SIZE ); free( ptr ); ptr = NULL; /* Funkcja wywo�ana w celu sprawdzenia zakresu pocz�tkowego */ if( type == 0 ) { strncpy( temp_r, strstr( range, "=" ), SMALL_BUFF_SIZE ); len = strlen( temp_r ); temp_r[ len-1 ] = '\0'; for( i = 0; i < len; ++i ) { if( i < len ) { temp_r[ i ] = temp_r[ i+1 ] ; } } } else if( type == 1 ) { /* Funkcja wywo�ana w celu sprawdzenia zakresu ko�cowego */ strncpy( temp_r, strrchr( range, '-' ), SMALL_BUFF_SIZE ); len = strlen( temp_r ); /* Usuni�cie znaku "-" pozosta�ego po strrchr() */ for( i = 0; i < len; ++i ) { if( i < len ) { temp_r[ i ] = temp_r[ i+1 ]; } } } /* Konwersja ci�gu znak�w na liczb� */ range_s = atoi( temp_r ); free( range ); range = NULL; free( temp_r ); temp_r = NULL; return range_s; }
/* REQUEST_process( HTTP_SESSION *http_session ) @http_session - wska�nik do pod��czonego klienta - po udanej weryfikacji danych przechodzi do pr�by przes�ania ��danego zasobu */ void REQUEST_process( HTTP_SESSION *http_session ) { char *local_file_path; /* Lokalna �cie�ka do ��danego pliku */ char *file_ext; /* Rozszerzenie ��danego pliku */ char *add_hdr; /* Opcjonalne nag��wki */ char *ht_access_pwd; /* Has�o do ��danego zasobu z funkcji file_params*/ int len_loc; /* D�ugo�� ��danej �cie�ki */ int file_params_val = 0; /* Przechowuje wynik dzia�ania funkcji file_params */ len_loc = strlen( http_session->http_info.http_local_path ); /* Przygotowanie pami�ci na nazw� ��danego pliku */ local_file_path = malloc( MAX_PATH_LENGTH_CHAR+1 ); mem_allocated( local_file_path, 34 ); /* Po��czenie �cie�ki z ��dania z pe�n� �cie�k� w systemie*/ if( len_loc > 1 ) { /* Stworzenie lokalnej �cie�ki dost�pu do zasobu */ strncpy( local_file_path, app_path, MAX_PATH_LENGTH ); strncat( local_file_path, http_session->http_info.http_local_path, MAX_PATH_LENGTH ); } else { /* Jeste�my w g��wnym katalogu */ strncpy( local_file_path, app_path, MAX_PATH_LENGTH ); } /* Zamiana znaku "/" z request na "\" - tylko Win32*/ strrepchar( local_file_path, '/', C_SLASH ); /* Usuni�cie podw�jnych znak�w slash */ strdelbslash( local_file_path ); /* Je�eli podano sam� nazw� katalogu to automatycznie dodajemy plik indeksu - tu juz po weryfikacji, czy zasob jest skryptem CGI */ if( strncmp( file_get_name( local_file_path ), "", 1 ) == 0 ) { strncat( local_file_path, REQUEST_get_index( local_file_path ), MAX_PATH_LENGTH ); } if( ht_access_count > 0 ) { /* Alokacja pami�ci */ ht_access_pwd = malloc( STD_BUFF_SIZE_CHAR ); mem_allocated( ht_access_pwd, 35 ); } /*Sprawdzamy, czy ��dany plik istnieje... */ file_params_val = file_params( http_session, local_file_path, (ht_access_count > 0 ? ht_access_pwd : NULL ) ); if( file_params_val == 0 ) { /* Plik nie istnieje */ file_ext = malloc( MICRO_BUFF_SIZE_CHAR ); strncpy( file_ext, file_get_ext( local_file_path ), MICRO_BUFF_SIZE ); /*...brak rozszerzenia = nie podano konkretnego pliku w URL... */ if( strncmp( file_ext, "", MICRO_BUFF_SIZE ) == 0 ) { /*...sprawdzamy, czy ostatni znak to "/"... */ if( local_file_path[ strlen( local_file_path )-1 ] != C_SLASH ) { /*...mimo wszystko sprawdzamy, czy �cie�ka jest prawid�owa. Tak = b��d 302. Nie = b��d 400. */ if( directory_exists( local_file_path ) ) { /* Stworzenie dodatkowej informacji do nag��wna wysy�anego przez RESPONSE_error z prawid�ow� �cie�k� */ add_hdr = malloc( MAX_PATH_LENGTH_CHAR ); sprintf( add_hdr, "%s%s/\r\n", HEADER_LOCATION, http_session->http_info.http_local_path ); RESPONSE_error( http_session, HTTP_302_FOUND, HTTP_ERR_302_MSG, add_hdr ); free( add_hdr ); add_hdr = NULL; } else { RESPONSE_error( http_session, HTTP_400_BAD_REQUEST, HTTP_ERR_400_MSG, NULL ); } } else { /*...plik nie istnieje, a index.html brak... */ RESPONSE_error( http_session, HTTP_404_NOT_FOUND, HTTP_ERR_404_MSG, NULL ); } } else { RESPONSE_error( http_session, HTTP_404_NOT_FOUND, HTTP_ERR_404_MSG, NULL ); } /* Zwolnienie pami�ci dla rozszerzenia ��danego pliku */ free( file_ext ); file_ext = NULL; } else { /* Plik istnieje, ale jakie ma w�a�ciwo�ci ? */ if( file_params_val == 1 ) { /* Plik istnieje i jest do odczytu */ /* Je�eli jest to skrypt CGI, to zostaje wykonany */ /* Zwyk�e ��danie zasobu */ /*Zapytanie zweryfikowane - wysy�ka zawarto�ci zasobu */ if( http_session->http_info.method_name != POST ) { RESPONSE_file( http_session, local_file_path ); /* Zapytanie HEAD jest weryfikowane w funkcji RESPONSE_header */ } } else if( file_params_val == 2 ) {/* Plik istnieje, ale dost�p jest zabroniony */ RESPONSE_error( http_session, HTTP_403_FORBIDDEN, HTTP_ERR_403_MSG, NULL ); } else if( file_params_val == 3 ) {/* Plik istnieje, ale wymaga autoryzacji */ if( http_session->http_info.authorization ) { if( strncmp( ht_access_pwd, http_session->http_info.authorization, STD_BUFF_SIZE ) == 0 ) { /* Zwyk�e ��danie zasobu */ /*Zapytanie zweryfikowane - wysy�ka zawarto�ci zasobu */ if( http_session->http_info.method_name != POST ) { RESPONSE_file( http_session, local_file_path ); /* Zapytanie HEAD jest weryfikowane w funkcji RESPONSE_header */ } else { RESPONSE_error( http_session, HTTP_401_AUTHORIZATION_REQUIRED, HTTP_ERR_401_MSG, HEADER_AUTHENTICATION ); } } else { RESPONSE_error( http_session, HTTP_401_AUTHORIZATION_REQUIRED, HTTP_ERR_401_MSG, HEADER_AUTHENTICATION ); } } else { RESPONSE_error( http_session, HTTP_401_AUTHORIZATION_REQUIRED, HTTP_ERR_401_MSG, HEADER_AUTHENTICATION ); } } } if( ht_access_count > 0) { /* Zwolnienie pami�ci dla has�a zasobu */ if( ht_access_pwd ) { free( ht_access_pwd ); ht_access_pwd = NULL; } } /* Zwolnienie pami�ci dla nazwy ��danego pliku */ free( local_file_path ); local_file_path = NULL; /* Zwalniamy pami�� */ SESSION_release( http_session ); }
/* RESPONSE_file( HTTP_SESSION *http_session, const char *filename ) @http_session - wska�nik do pod��czonego klienta @filename - nazwa pliku, kt�ry ma zosta� przes�any - funkcja wysy�a do przegl�darki ��dany zas�b lub jego fragment */ void RESPONSE_file( HTTP_SESSION *http_session, const char *filename ) { FILE *file; long filesize = 0; /* Ca�kowity rozmiar ��danego pliku */ long total = 0; /* Ca�kowity rozmiar wysy�anych danych */ char *buf; char *add_hdr; /* Opcjonalne nag��wki */ SEND_INFO *send_struct; /* Otwarcie pliku. Weryfikacja poprawno�ci jego nazwy nast�pi�a poprzez funkcj� file_params w nadrz�dnej funkcji REQUEST_process */ file = battery_fopen( filename, READ_BINARY, 1, http_session->socket_descriptor, STD_FILE ); /* Nie uda�o si� otworzy� pliku, cho� istnieje - problem z serwerem? */ if( !file ) { RESPONSE_error( http_session, HTTP_500_SERVER_ERROR, HTTP_ERR_500_MSG, NULL ); } else { /* Sprawdzenie, czy istnieje nag��wek "If-Modified-Since" */ if( http_session->http_info.date_if_modified_since ) { /* Por�wnanie nag��wka "If-Modified-Since" z dat� modyfikacji pliku */ if( strcmp( http_session->local_info.date_res_last_modified, http_session->http_info.date_if_modified_since ) == 0 ) { battery_fclose( file, http_session->socket_descriptor ); RESPONSE_header( http_session, HTTP_304_NOT_MODIFIED, HEADER_STD_CONTENT_TYPE, 0, NULL, NULL ); return; } } /* Sprawdzenie, czy istnieje nag��wek "If-Unmodified-Since" */ if( http_session->http_info.date_if_unmodified_since ) { /* Por�wnanie nag��wka "If-Unmodified-Since" z dat� modyfikacji pliku */ if( strcmp( http_session->local_info.date_res_last_modified, http_session->http_info.date_if_unmodified_since ) != 0 ) { battery_fclose( file, http_session->socket_descriptor ); RESPONSE_header( http_session, HTTP_412_PRECONDITION_FAILED, HEADER_STD_CONTENT_TYPE, 0, NULL, NULL ); return; } } /* Pobranie rozmiaru pliku */ filesize = battery_ftell( file ); /* Plik jest pusty = b��d 204 */ if( filesize <= 0 ) { RESPONSE_error( http_session, HTTP_204_NO_CONTENT, HTTP_ERR_204_MSG, NULL ); } else { /* Nie wybrano �adnego fragmentu pliku - brak nag��wka "Range" */ if( ( http_session->http_info.range_st < 0 )&&( http_session->http_info.range_en < 0 ) ) { /* Wysy�ka z kodem 200 - wszystko ok */ RESPONSE_header( http_session, HTTP_200_OK, REQUEST_get_mime_type( filename ), filesize, NULL, NULL ); send_struct = SESSION_find_response_struct_by_id( http_session->socket_descriptor ); if( send_struct ) { send_struct->file = file; send_struct->http_content_size = filesize; send_struct->sent_size = 0; } } else { /* Wysy�ka wybranego fragmentu pliku */ /* Je�eli zakres ko�cowy jest mniejszy od 0 ( np. -1 ) to ustawiamy go jako rozmiar pliku */ if( http_session->http_info.range_en <= 0 ) { http_session->http_info.range_en = filesize; } /* Ca�kowity rozmiar fragmentu */ http_session->http_info.range_en--; /* bajt zerowy! */ total = http_session->http_info.range_en - http_session->http_info.range_st; /* Brak podanego zakresu w pliku lub b��dny zakres = b��d 416 */ if( ( fseek( file, http_session->http_info.range_st, SEEK_SET ) != 0 ) || ( total <= 0 ) ) { RESPONSE_error( http_session, HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE, HTTP_ERR_416_MSG, NULL ); } else { /* Dodanie nag��wka "Content-Range" */ add_hdr = malloc( STD_BUFF_SIZE_CHAR ); mem_allocated( add_hdr, 32 ); sprintf( add_hdr, "%sbytes %ld-%ld/%ld\r\n", HEADER_CONTENT_RANGE, http_session->http_info.range_st, http_session->http_info.range_en, filesize ); /* Wysy�ka z kodem 206 - wybrany fragment zasobu */ RESPONSE_header( http_session, HTTP_206_PARTIAL_CONTENT, REQUEST_get_mime_type( filename ), total+1, NULL, add_hdr ); free( add_hdr ); add_hdr = NULL; /* Wczytanie fragmentu i wysy�ka */ buf = malloc( total ); mem_allocated( buf, 33 ); if( fread( buf, sizeof( char ), total, file ) > 0 ) { SESSION_send_response( http_session, buf, total+1 ); } else { /* Napotkano b��d = 500 */ RESPONSE_error( http_session, HTTP_500_SERVER_ERROR, HTTP_ERR_500_MSG, NULL ); } free( buf ); buf = NULL; } } } } }
/* RESPONSE_header( HTTP_SESSION *http_session, const char *http_status_code, const char *http_mime_type, size_t http_content_length, char *time_last_modified, const char *content_data, const char* add_headers ) @http_session - wska�nik do po��czonego klienta @http_status_code - kod odpowiedzi @http_mime_type - typ mime @http_content_length - rozmiar wysy�anych danych @time_last_modified - data ostatniej modyfikacji pliku ( 0 je�eli nag��wek Last-Modified ma nie zosta� do��czony @content_data - tre�� wysy�anej wiadomo�ci @add_headers - dodatkowe nag��wki ( ustawione w funkcji wywo�uj�cej i przekazane przez ten parametr - g��wna funkcja wysy�aj�ca odpowied� do klienta: header + ewentualny content */ void RESPONSE_header( HTTP_SESSION *http_session, const char *http_status_code, const char *http_mime_type, size_t http_content_length, const char *content_data, const char* add_headers ) { char *http_header_to_send; /* Przechowuje tre�� HEADER */ char *http_single_header_line; /* Pojedyncza linia nag��wka */ /* Alokacja pami�ci */ http_header_to_send = malloc( MAX_BUFFER_CHAR+1 ); mem_allocated( http_header_to_send, 28 ); http_single_header_line = malloc( STD_BUFF_SIZE_CHAR ); mem_allocated( http_single_header_line, 29 ); /* HTTP/1.1 KOD OPIS */ sprintf( http_single_header_line, "%s %s\r\n", HTTP_VER, http_status_code ); strncpy( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Date: */ sprintf( http_single_header_line, "%s%s\r\n", HEADER_DATE, get_actual_time_gmt() ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Server: */ sprintf( http_single_header_line, "%s\r\n", HEADER_SERVER ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); /* Accept Ranges: bytes */ strncat( http_header_to_send, HEADER_ACCEPT_RANGES, MAX_BUFFER ); /* Content-Type: */ if( http_mime_type ) { sprintf( http_single_header_line, "%s%s\r\n", HEADER_CONTENT_TYPE, http_mime_type ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); } /* Connection: Keep-Alive */ if( http_session->http_info.keep_alive ) { sprintf( http_single_header_line, "%s%s\r\n", HEADER_CONNECTION, HEADER_KEEP_ALIVE_STR ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); } /* Content-Length: */ if( http_content_length != 0 ) { sprintf( http_single_header_line,"%s%zu\r\n", HEADER_CONTENT_LENGTH, http_content_length ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); } /* Last-Modified: */ if( http_session->local_info.date_res_last_modified ) { sprintf( http_single_header_line, "%s%s\r\n", HEADER_LAST_MODIFIED, http_session->local_info.date_res_last_modified ); strncat( http_header_to_send, http_single_header_line, MAX_BUFFER ); } /* Dodatkowe nag��wki? */ if( add_headers ) { strncat( http_header_to_send, add_headers, MAX_BUFFER ); } /* Pusta linia - po niej zaczyna si� content */ strncat( http_header_to_send, "\r\n", MAX_BUFFER ); /* Wysy�ka nag��wka HTTP */ if( SESSION_send_response( http_session, http_header_to_send, strlen( http_header_to_send ) ) > 0 ) { /* Wysy�ka contentu */ if( content_data ) { SESSION_send_response( http_session, content_data, http_content_length ); } } /* Zapis ��dania do logu */ LOG_print( "%s %s %s \"%s\" %s %.3s\n", get_actual_time_gmt(), http_session->http_info.remote_addr, http_method_list[ http_session->http_info.method_name ], http_session->http_info.http_local_path, http_session->http_info.protocol_ver, http_status_code ); /* Zwolnienie pami�ci */ free( http_header_to_send ); http_header_to_send = NULL; free( http_single_header_line ); http_single_header_line = NULL; }
/* --------------------- main ---------------------- */ int __CDECL main(int ac, char *av[]) { Lstr args[MAXARGS], tracestr, file; int ia,ir,iaa; bool input, loop_over_stdin, parse_args, interactive; #ifdef HAVE_READLINE Lstr line; LINITSTR(line); #endif input = FALSE; loop_over_stdin = FALSE; parse_args = FALSE; interactive = FALSE; for (ia=0; ia<MAXARGS; ia++) LINITSTR(args[ia]); LINITSTR(tracestr); LINITSTR(file); if (ac<2) { #if defined(JCC) puts("\nsyntax: rexx [-[trace]|-F|-a|-i|-m] <filename> <args>...\n"); #else puts("\nsyntax: rexx [-[trace]|-F|-a|-i] <filename> <args>...\n"); #endif puts("options:"); puts("\t-\tto use stdin as input file"); puts("\t-a\tbreak words into multiple arguments"); puts("\t-i\tenter interactive mode"); puts("\t-F\tloop over standard input"); puts("\t\t\'linein\' contains each line from stdin."); #ifdef JCC puts(" -m machine architecture: 0=S/370, 1=Hercules s37x, 2=S/390, 3=z/Arch."); puts("\n"); #endif puts(VERSIONSTR); puts("Author: "AUTHOR); puts("Please report bugs, errors or comments to the above address.\n"); return 0; } #ifdef __DEBUG__ __debug__ = FALSE; #endif /* --- Initialise --- */ RxInitialize(av[0]); /* --- Register functions of external libraries --- */ #ifdef STATIC RxMySQLInitialize(); RxSQLiteInitialize(); #endif #ifdef RXCONIO RxConIOInitialize(); #endif /* --- scan arguments --- */ ia = 1; if (av[ia][0]=='-') { if (av[ia][1]==0) input = TRUE; else if (av[ia][1]=='F') loop_over_stdin = input = TRUE; else if (av[ia][1]=='a') parse_args = TRUE; else if (av[ia][1]=='i') interactive = TRUE; #ifdef JCC else if (av[ia][1]=='m') __libc_arch = atoi(av[ia]+2); #endif else Lscpy(&tracestr,av[ia]+1); ia++; } else if (av[ia][0]=='?' || av[ia][0]=='!') { Lscpy(&tracestr,av[ia]); ia++; } /* --- let's read a normal file --- */ if (!input && !interactive && ia<ac) { /* prepare arguments for program */ iaa = 0; for (ir=ia+1; ir<ac; ir++) { if (parse_args) { Lscpy(&args[iaa], av[ir]); if (++iaa >= MAXARGS) break; } else { Lcat(&args[0], av[ir]); if (ir<ac-1) Lcat(&args[0]," "); } } RxRun(av[ia],NULL,args,&tracestr,NULL); } else { if (interactive) Lcat(&file, "signal on syntax;" "signal on error;" "signal on halt;" "start:do forever;" "call write ,\">>> \";" " parse pull _;" " result=@r;" " interpret _;" " @r=result;" "end;" "signal start;" "syntax:;error: say \"+++ Error\" RC\":\" errortext(RC);" "signal start;" "halt:"); else if (ia>=ac) { #ifndef HAVE_READLINE Lread(STDIN,&file,LREADFILE); #else struct stat buf; fstat(0,&buf); if (S_ISCHR(buf.st_mode)) { printf("End with \";\" on a line by itself.\n"); while (1) { Lread(STDIN,&line,LREADLINE); if (!Lcmp(&line,";")) break; Lstrcat(&file,&line); Lcat(&file,"\n"); } } else Lread(STDIN,&file,LREADFILE); #endif } else { /* Copy a small header */ if (loop_over_stdin) Lcat(&file,"do forever;" "linein=read();" "if eof(0) then exit;"); for (;ia<ac; ia++) { Lcat(&file,av[ia]); if (ia<ac-1) Lcat(&file," "); } /* and a footer */ if (loop_over_stdin) Lcat(&file,";end"); } RxRun(NULL,&file,args,&tracestr,NULL); } /* --- Free everything --- */ RxFinalize(); for (ia=0; ia<MAXARGS; ia++) LFREESTR(args[ia]); LFREESTR(tracestr); LFREESTR(file); #ifdef HAVE_READLINE LFREESTR(line); #endif #ifdef STATIC RxMySQLFinalize(); RxSQLiteFinalize(); #endif #ifdef __DEBUG__ if (mem_allocated()!=0) { fprintf(STDERR,"\nMemory left allocated: %ld\n",mem_allocated()); mem_list(); } #endif return rxReturnCode; } /* main */
/* Use this function to track memory allocation performance. * This function does not depend on your implementation, * but on the functions you wrote above. */ void print_memory_status() { printf("%d out of %d bytes allocated.\n",mem_allocated(),mem_total()); printf("%d bytes are free in %d holes; maximum allocatable block is %d bytes.\n",mem_free(),mem_holes(),mem_largest_free()); printf("Average hole size is %f.\n\n",((float)mem_free())/mem_holes()); }