Add comments and error checking to A9
This commit is contained in:
		| @@ -7,16 +7,17 @@ | |||||||
| #include "png.h" | #include "png.h" | ||||||
|  |  | ||||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||||
|  | 	// Error handling | ||||||
| 	if (argc != 2) { | 	if (argc != 2) { | ||||||
| 		printf("Usage: %s <png file>\n", argv[0]); | 		printf("Usage: %s <png file>\n", argv[0]); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	if (strlen(argv[1]) > PATH_MAX) { | 	if (strlen(argv[1]) > PATH_MAX) { | ||||||
| 		printf("Path too long\n"); | 		printf("Path too long\n"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
|  | 	// Read file | ||||||
| 	char *path = argv[1]; | 	char *path = argv[1]; | ||||||
|  |  | ||||||
| 	char *png_buffer = load_file(get_fd(path)); | 	char *png_buffer = load_file(get_fd(path)); | ||||||
| 	if (!is_png(png_buffer)) { | 	if (!is_png(png_buffer)) { | ||||||
| 		printf("It's not a PNG file\n"); | 		printf("It's not a PNG file\n"); | ||||||
| @@ -26,6 +27,8 @@ int main(int argc, char *argv[]) { | |||||||
| 	} | 	} | ||||||
| 	png_chunk **chunks = get_png_chunks(png_buffer); | 	png_chunk **chunks = get_png_chunks(png_buffer); | ||||||
| 	free(png_buffer); | 	free(png_buffer); | ||||||
|  | 	// Done with buffer, as chunks are a structured way to access the data | ||||||
|  | 	// Iterate over chunks to display info and "decrypt" IDAT chunks | ||||||
| 	int size = get_number_of_chunks(chunks); | 	int size = get_number_of_chunks(chunks); | ||||||
| 	for (int i = 0; i < size; i++) { | 	for (int i = 0; i < size; i++) { | ||||||
| 		// Check if header is IDAT or IEND | 		// Check if header is IDAT or IEND | ||||||
| @@ -41,11 +44,7 @@ int main(int argc, char *argv[]) { | |||||||
| 		} | 		} | ||||||
| 		printf("Chunk size is:%d\n", chunks[i]->length); | 		printf("Chunk size is:%d\n", chunks[i]->length); | ||||||
| 	} | 	} | ||||||
| 	// Uncomment to not overwrite original file | 	// Write file and free memory | ||||||
| 	//char new_path[PATH_MAX]; |  | ||||||
| 	//getcwd(new_path, sizeof(new_path)); |  | ||||||
| 	//strcat(new_path, "/output.png"); |  | ||||||
| 	//write_png_chunks(new_path, chunks); |  | ||||||
| 	write_png_chunks(path, chunks); | 	write_png_chunks(path, chunks); | ||||||
| 	destroy_chunks(chunks); | 	destroy_chunks(chunks); | ||||||
| 	return EXIT_SUCCESS; | 	return EXIT_SUCCESS; | ||||||
|   | |||||||
| @@ -39,12 +39,12 @@ int get_fd(char *path) { | |||||||
| 	FILE *fp = fopen(path, "rb"); | 	FILE *fp = fopen(path, "rb"); | ||||||
| 	if (fp == NULL) { | 	if (fp == NULL) { | ||||||
| 		perror("fopen"); | 		perror("fopen"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	int fd = fileno(fp); | 	int fd = fileno(fp); | ||||||
| 	if (fd == -1) { | 	if (fd == -1) { | ||||||
| 		perror("fileno"); | 		perror("fileno"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	return fd; | 	return fd; | ||||||
| } | } | ||||||
| @@ -53,7 +53,7 @@ FILE *get_fp(int fd) { | |||||||
| 	FILE *fp = fdopen(fd, "rb"); | 	FILE *fp = fdopen(fd, "rb"); | ||||||
| 	if (fp == NULL) { | 	if (fp == NULL) { | ||||||
| 		perror("fdopen"); | 		perror("fdopen"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	return fp; | 	return fp; | ||||||
| } | } | ||||||
| @@ -66,7 +66,7 @@ char *load_file(int fd) { | |||||||
| 	char *buffer = malloc(size); | 	char *buffer = malloc(size); | ||||||
| 	if (buffer == NULL) { | 	if (buffer == NULL) { | ||||||
| 		perror("malloc"); | 		perror("malloc"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	fread(buffer, 1, size, fp); | 	fread(buffer, 1, size, fp); | ||||||
| 	fclose(fp); | 	fclose(fp); | ||||||
| @@ -81,15 +81,16 @@ png_chunk *get_png_chunk(char *buffer, unsigned int offset) { | |||||||
| 	png_chunk *chunk = malloc(sizeof(png_chunk)); | 	png_chunk *chunk = malloc(sizeof(png_chunk)); | ||||||
| 	if (chunk == NULL) { | 	if (chunk == NULL) { | ||||||
| 		perror("malloc"); | 		perror("malloc"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	memcpy(&chunk->length, buffer + offset + 0, 4); | 	memcpy(&chunk->length, buffer + offset + 0, 4); | ||||||
|  | 	// Convert length to host byte order because PNG lengths is in network byte order/Big Endian | ||||||
| 	chunk->length = ntohl(chunk->length); | 	chunk->length = ntohl(chunk->length); | ||||||
| 	memcpy(&chunk->type, buffer + offset + 4, 4); | 	memcpy(&chunk->type, buffer + offset + 4, 4); | ||||||
| 	chunk->data = malloc(chunk->length); | 	chunk->data = malloc(chunk->length); | ||||||
| 	if (chunk->data == NULL) { | 	if (chunk->data == NULL) { | ||||||
| 		perror("malloc"); | 		perror("malloc"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	memcpy(chunk->data, buffer + offset + 8, chunk->length); | 	memcpy(chunk->data, buffer + offset + 8, chunk->length); | ||||||
| 	memcpy(&chunk->crc, buffer + offset + 8 + chunk->length, 4); | 	memcpy(&chunk->crc, buffer + offset + 8 + chunk->length, 4); | ||||||
| @@ -100,9 +101,11 @@ png_chunk **get_png_chunks(char *buffer) { | |||||||
| 	png_chunk **chunks = malloc(sizeof(png_chunk *)); | 	png_chunk **chunks = malloc(sizeof(png_chunk *)); | ||||||
| 	if (chunks == NULL) { | 	if (chunks == NULL) { | ||||||
| 		perror("malloc"); | 		perror("malloc"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
|  | 	// Running offset of the buffer | ||||||
| 	unsigned int offset = PNG_SIGNATURE_SIZE; | 	unsigned int offset = PNG_SIGNATURE_SIZE; | ||||||
|  | 	// Index of the current chunk | ||||||
| 	int i = 0; | 	int i = 0; | ||||||
| 	while (true) { | 	while (true) { | ||||||
| 		chunks[i] = get_png_chunk(buffer, offset); | 		chunks[i] = get_png_chunk(buffer, offset); | ||||||
| @@ -112,11 +115,14 @@ png_chunk **get_png_chunks(char *buffer) { | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		i++; | 		i++; | ||||||
| 		chunks = realloc(chunks, sizeof(png_chunk *) * (i + 1)); | 		// Add one because realloc is 1-indexed when multiplying by sizeof | ||||||
| 		if (chunks == NULL) { | 		png_chunk **err_check = realloc(chunks, sizeof(png_chunk *) * (i + 1)); | ||||||
|  | 		if (err_check == NULL) { | ||||||
|  | 			destroy_chunks(chunks); | ||||||
| 			perror("realloc"); | 			perror("realloc"); | ||||||
| 			exit(1); | 			exit(EXIT_FAILURE); | ||||||
| 		} | 		} | ||||||
|  | 		chunks = err_check; | ||||||
| 	} | 	} | ||||||
| 	return chunks; | 	return chunks; | ||||||
| } | } | ||||||
| @@ -126,6 +132,7 @@ int get_number_of_chunks(png_chunk **chunks) { | |||||||
| 	while (memcmp(chunks[i]->type, "IEND", 4) != 0) { | 	while (memcmp(chunks[i]->type, "IEND", 4) != 0) { | ||||||
| 		i++; | 		i++; | ||||||
| 	} | 	} | ||||||
|  | 	// Add one for the IEND chunk | ||||||
| 	return ++i; | 	return ++i; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -148,14 +155,16 @@ void write_png_chunks(char *path, png_chunk **chunks) { | |||||||
| 	FILE *fp = fopen(path, "wb"); | 	FILE *fp = fopen(path, "wb"); | ||||||
| 	if (fp == NULL) { | 	if (fp == NULL) { | ||||||
| 		perror("fopen"); | 		perror("fopen"); | ||||||
| 		exit(1); | 		exit(EXIT_FAILURE); | ||||||
| 	} | 	} | ||||||
| 	fwrite(PNG_SIGNATURE, PNG_SIGNATURE_SIZE, 1, fp); | 	fwrite(PNG_SIGNATURE, PNG_SIGNATURE_SIZE, 1, fp); | ||||||
| 	unsigned int size = get_number_of_chunks(chunks); | 	unsigned int size = get_number_of_chunks(chunks); | ||||||
| 	for (int i = 0; i < size; i++) { | 	for (int i = 0; i < size; i++) { | ||||||
|  | 		// Convert length to network byte order for writing | ||||||
| 		chunks[i]->length = htonl(chunks[i]->length); | 		chunks[i]->length = htonl(chunks[i]->length); | ||||||
| 		fwrite(&chunks[i]->length, 4, 1, fp); | 		fwrite(&chunks[i]->length, 4, 1, fp); | ||||||
| 		fwrite(chunks[i]->type, 4, 1, fp); | 		fwrite(chunks[i]->type, 4, 1, fp); | ||||||
|  | 		// Convert back so we can accurately use it to write the length of the data | ||||||
| 		chunks[i]->length = ntohl(chunks[i]->length); | 		chunks[i]->length = ntohl(chunks[i]->length); | ||||||
| 		fwrite(chunks[i]->data, chunks[i]->length, 1, fp); | 		fwrite(chunks[i]->data, chunks[i]->length, 1, fp); | ||||||
| 		fwrite(&chunks[i]->crc, 4, 1, fp); | 		fwrite(&chunks[i]->crc, 4, 1, fp); | ||||||
|   | |||||||
| @@ -30,15 +30,14 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | // Needed for uint types | ||||||
| #include <arpa/inet.h> | #include <arpa/inet.h> | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
|  |  | ||||||
| // http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature | // http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature | ||||||
| #define PNG_SIGNATURE "\211PNG\r\n\032\n" | #define PNG_SIGNATURE "\211PNG\r\n\032\n" | ||||||
| #define PNG_SIGNATURE_SIZE 8 | #define PNG_SIGNATURE_SIZE 8 | ||||||
|  |  | ||||||
|  | // The key used to "encrypt/decrypt" the PNG chunks | ||||||
| #define KEY 42 | #define KEY 42 | ||||||
|  |  | ||||||
| typedef struct png_chunk { | typedef struct png_chunk { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user