/* * Copyright Notice * ---------------- * Copyright © 1998, 1999 by: Glenn Randers-Pehrson * This specification is a modification of the PNG 1.0 specification. It is being * provided by the copyright holder under the provisions of the 1996 MIT copyright and license: * Copyright © 1996 by: Massachusetts Institute of Technology (MIT) * This W3C specification is being provided by the copyright holders under * the following license. By obtaining, using and/or copying this specification, you * agree that you have read, understood, and will comply with the following terms * and conditions: * Permission to use, copy, and distribute this specification for any purpose * and without fee or royalty is hereby granted, provided that the full text of * this NOTICE appears on ALL copies of the specification or portions thereof, * including modifications, that you make. * THIS SPECIFICATION IS PROVIDED ”AS IS,” AND COPYRIGHT HOLD-ERS * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR * IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT * HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY * OR FITNESS FOR ANY PARTICULAR PURPOSE OR * THAT THE USE OF THE SPECIFICATION WILL NOT INFRINGE ANY * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER * RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY * USE OF THIS SPECIFICATION. * The name and trademarks of copyright holders may NOT be used in * advertising or publicity pertaining to the specification without specific, written * prior permission. Title to copyright in this specification and any associated * documentation will at all times remain with copyright holders. */ #include #include #include #include #include #include "png.h" int get_fd(char *path) { FILE *fp = fopen(path, "rb"); if (fp == NULL) { perror("fopen"); exit(1); } int fd = fileno(fp); if (fd == -1) { perror("fileno"); exit(1); } return fd; } FILE *get_fp(int fd) { FILE *fp = fdopen(fd, "rb"); if (fp == NULL) { perror("fdopen"); exit(1); } return fp; } char *load_file(int fd) { FILE *fp = get_fp(fd); fseek(fp, 0, SEEK_END); long size = ftell(fp); rewind(fp); char *buffer = malloc(size); if (buffer == NULL) { perror("malloc"); exit(1); } fread(buffer, 1, size, fp); fclose(fp); return buffer; } int is_png(char *buffer) { return memcmp(buffer, PNG_SIGNATURE, PNG_SIGNATURE_SIZE) == 0; } png_chunk *get_png_chunk(char *buffer, unsigned int offset) { png_chunk *chunk = malloc(sizeof(png_chunk)); if (chunk == NULL) { perror("malloc"); exit(1); } memcpy(&chunk->length, buffer + offset + 0, 4); chunk->length = ntohl(chunk->length); memcpy(&chunk->type, buffer + offset + 4, 4); chunk->data = malloc(chunk->length); if (chunk->data == NULL) { perror("malloc"); exit(1); } memcpy(chunk->data, buffer + offset + 8, chunk->length); memcpy(&chunk->crc, buffer + offset + 8 + chunk->length, 4); return chunk; } png_chunk **get_png_chunks(char *buffer) { png_chunk **chunks = malloc(sizeof(png_chunk *)); if (chunks == NULL) { perror("malloc"); exit(1); } unsigned int offset = PNG_SIGNATURE_SIZE; int i = 0; while (true) { chunks[i] = get_png_chunk(buffer, offset); // 12 = 4 (length) + 4 (type) + 4 (crc) offset += 12 + chunks[i]->length; if (memcmp(chunks[i]->type, "IEND", 4) == 0) { break; } i++; chunks = realloc(chunks, sizeof(png_chunk *) * (i + 1)); if (chunks == NULL) { perror("realloc"); exit(1); } } return chunks; } int get_number_of_chunks(png_chunk **chunks) { int i = 0; while (memcmp(chunks[i]->type, "IEND", 4) != 0) { i++; } return ++i; } void xor_data(png_chunk *chunk) { for (int i = 0; i < chunk->length; i++) { chunk->data[i] ^= KEY; } } void destroy_chunks(png_chunk **chunks) { unsigned int size = get_number_of_chunks(chunks); for (int i = 0; i < size; i++) { free(chunks[i]->data); free(chunks[i]); } free(chunks); } void write_png_chunks(char *path, png_chunk **chunks) { FILE *fp = fopen(path, "wb"); if (fp == NULL) { perror("fopen"); exit(1); } fwrite(PNG_SIGNATURE, PNG_SIGNATURE_SIZE, 1, fp); unsigned int size = get_number_of_chunks(chunks); for (int i = 0; i < size; i++) { chunks[i]->length = htonl(chunks[i]->length); fwrite(&chunks[i]->length, 4, 1, fp); fwrite(chunks[i]->type, 4, 1, fp); chunks[i]->length = ntohl(chunks[i]->length); fwrite(chunks[i]->data, chunks[i]->length, 1, fp); fwrite(&chunks[i]->crc, 4, 1, fp); } fclose(fp); }