[c] base64

/** Program:
* base64 encode & decode
* Author:
* brant-ruan
* Date:
* 2016-02-29
* Usage:
* Encode:
* ./base64 -e src-file dst-file
* Decode:
* ./base64 -d src-file dst-file
* P.S.
* To use this tool correctly, you must ensure that your src-file is valid.
**/

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#define OK 0
#define ERROR -1
#define CHART_SIZE 64

typedef int Status;

// standard base64 encoding chart
char std_chart[CHART_SIZE+1] = {
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/"
};

Status Encode(char *input, char *output);
Status Decode(char *input, char *output);
void MsgPrt(char *msg);

int main(int argc, char **argv)
{
    if(argc != 4){
        MsgPrt(argv[0]);
    }
    else if(strcmp("-e", argv[1]) == 0){
        Encode(argv[2], argv[3]);
    }
    else if(strcmp("-d", argv[1]) == 0){
        Decode(argv[2], argv[3]);
    }
    else{
        MsgPrt(argv[0]);
    }

    return OK;
}

/* print error when arguments error happen */
void MsgPrt(char *msg)
{
    printf("Usage:\n"); 
    printf("\tEncode: %s -e src-file des-file\n", msg);
    printf("\tDecode: %s -d src-file des-file\n", msg);
}

/* print error information and exit */
void ErrorPrint(char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(0);
}

/* base64 encoding */
Status Encode(char *input, char *output)
{
    FILE *fpi;
    FILE *fpo;
    if((fpi = fopen(input, "r")) == NULL) 
        ErrorPrint(input); // if can not open input file

    if((fpo = fopen(output, "w")) == NULL) 
        ErrorPrint(output); // if can not open output file

    char in[3];
    char tempc;
    int i = 0;

    while((tempc = fgetc(fpi)) != EOF){
        in[i++] = tempc;
        if(i == 3){
            // char 1
            tempc = (in[0] >> 2) & 0x3f;
            fputc(std_chart[tempc], fpo);
            // char 2
            tempc = ((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f);
            fputc(std_chart[tempc], fpo);
            // char 3
            tempc = ((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03);
            fputc(std_chart[tempc], fpo);
            // char 4
            tempc = in[2] & 0x3f;
            fputc(std_chart[tempc], fpo);
            // initialize 'i'
            i = 0;
        }

    }
    // if the file's size is not times of 3:
    if(i != 0){
        tempc = (in[0] >> 2) & 0x3f;
        fputc(std_chart[tempc], fpo);
    }
    if(i == 1){ // if there is 1 byte rest
        tempc = (in[0] << 4) & 0x30;
        fputc(std_chart[tempc], fpo);
        fputc('=', fpo);
        fputc('=', fpo);
    }
    if(i == 2){ // if there are 2 bytes rest
        tempc = ((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f);
        fputc(std_chart[tempc], fpo);
        tempc = (in[1] << 2) & 0x3c;
        fputc(std_chart[tempc], fpo);
        fputc('=', fpo);
    }

    fclose(fpi);
    fclose(fpo);

    return OK;
}

/* return the index of char in std_chart */
char ReIndex(char tempc)
{
    int i;
    for(i = 0; (i<CHART_SIZE) && (std_chart[i] != tempc); i++)
        ;
    if(i < CHART_SIZE)
        return i;

    return ERROR;
}

/* base64 decoding */
Status Decode(char *input, char *output)
{
    FILE *fpi;
    FILE *fpo;
    if((fpi = fopen(input, "r")) == NULL) 
        ErrorPrint(input); // if can not open input file

    if((fpo = fopen(output, "w")) == NULL) 
        ErrorPrint(output); // if can not open output file

    char in[4];
    char tempc;

    int i = 0;
    while((tempc = fgetc(fpi)) != EOF){
        if(tempc == '=') // go to Extra situation
            break;
        in[i++] = ReIndex(tempc);
        if(i == 4){
            // char 1
            tempc = (in[0] << 2) | ((in[1] >> 4) & 0x03);
            fputc(tempc, fpo);
            // char 2
            tempc = (in[1] << 4) | (in[2] >> 2);
            fputc(tempc, fpo);
            // char 3
            tempc = (in[2] << 6) | (in[3] & 0x3f);
            fputc(tempc, fpo);
            i = 0;
        }
    }
    if(tempc == '='){ // Extra situation
        tempc = (in[0] << 2) | ((in[1] >> 4) & 0x03);
        fputc(tempc, fpo);
        if(i == 3){
            tempc = (in[1] << 4) | (in[2] >> 2);
            fputc(tempc, fpo);
        }
    }
    fclose(fpi);
    fclose(fpo);

    return OK;
}

你可能感兴趣的:([c] base64)