|
|
1.1 root 1: /* base64.c */
2:
3: /* Base64 encoding/decoding routines */
4:
5: /* $Id: base64.c,v 1.21 2004/09/17 07:56:56 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include <stdlib.h>
39: #include <string.h>
40: #include "base64.h"
41:
42: static const char * base64alphabet =
43: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
44:
45: int b64_decode(char *target, size_t tlen, const char *source, size_t slen)
46: {
47: const char *inp;
48: char *outp;
49: char *outend;
50: const char *inend;
51: int bits=0;
52: int working=0;
53: char * i;
54:
55: if(slen==0)
56: slen=strlen(source);
57: outp=target;
58: inp=source;
59: outend=target+tlen;
60: inend=source+slen;
61: for(;outp<outend && inp<inend;inp++) {
62: working<<=6;
63: i=strchr(base64alphabet,(char)*inp);
64: if(i==NULL) {
65: return(-1);
66: }
67: if(*i=='=') { /* pad char */
68: if((working&0xFF) != 0)
69: return(-1);
70: break;
71: }
72: bits+=6;
73: working |= (i-base64alphabet);
74: if(bits>=8) {
75: *(outp++)=(char)((working&(0xFF<<(bits-8)))>>(bits-8));
76: bits-=8;
77: }
78: }
79: if(outp == outend) {
80: *(--outp)=0;
81: return(-1);
82: }
83: *outp=0;
84: return(outp-target);
85: }
86:
87: static int add_char(char *pos, char ch, int done, char *end)
88: {
89: if(pos>=end) {
90: return(1);
91: }
92: if(done)
93: *pos=base64alphabet[64];
94: else
95: *pos=base64alphabet[(int)ch];
96: return(0);
97: }
98:
99: int b64_encode(char *target, size_t tlen, const char *source, size_t slen) {
100: const char *inp;
101: char *outp;
102: char *outend;
103: const char *inend;
104: char *tmpbuf=NULL;
105: int done=0;
106: char enc;
107: int buf;
108:
109: if(slen==0)
110: slen=strlen(source);
111: inp=source;
112: if(source==target) {
113: tmpbuf=(char *)malloc(tlen);
114: if(tmpbuf==NULL)
115: return(-1);
116: outp=tmpbuf;
117: }
118: else
119: outp=target;
120:
121: outend=outp+tlen;
122: inend=inp+slen;
123: for(;(inp < inend) && !done;) {
124: enc=*(inp++);
125: buf=(enc & 0x03)<<4;
126: enc=(enc&0xFC)>>2;
127: if(add_char(outp++, enc, done, outend)) {
128: if(target==source)
129: free(tmpbuf);
130: return(-1);
131: }
132: enc=buf|((*inp & 0xF0) >> 4);
133: if(add_char(outp++, enc, done, outend)) {
134: if(target==source)
135: free(tmpbuf);
136: return(-1);
137: }
138: if(inp==inend)
139: done=1;
140: buf=(*(inp++)<<2)&0x3C;
141: enc=buf|((*inp & 0xC0)>>6);
142: if(add_char(outp++, enc, done, outend)) {
143: if(target==source)
144: free(tmpbuf);
145: return(-1);
146: }
147: if(inp==inend)
148: done=1;
149: enc=((int)*(inp++))&0x3F;
150: if(add_char(outp++, enc, done, outend)) {
151: if(target==source)
152: free(tmpbuf);
153: return(-1);
154: }
155: if(inp==inend)
156: done=1;
157: }
158: if(outp<outend)
159: *outp=0;
160: if(target==source) {
161: memcpy(target,tmpbuf,tlen);
162: free(tmpbuf);
163: }
164: return(outp-target);
165: }
166:
167: #ifdef BASE64_TEST
168: int main(int argc, char**argv)
169: {
170: int i,j;
171: char buf[512];
172:
173: for(i=1;i<argc;i++) {
174: j=b64_decode(buf,sizeof(buf),argv[i],0);
175: printf("%s (%d)\n",buf,j);
176: }
177:
178: return 0;
179: }
180: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.