|
|
1.1 root 1: /* base64.c */
2:
3: /* Base64 encoding/decoding routines */
4:
5: /* $Id: base64.c,v 1.23 2006/05/08 21:11:40 deuce 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: #include "gen_defs.h"
42:
43: static const char * base64alphabet =
44: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
45:
46: int b64_decode(char *target, size_t tlen, const char *source, size_t slen)
47: {
48: const char *inp;
49: char *outp;
50: char *outend;
51: const char *inend;
52: int bits=0;
53: int working=0;
54: char * i;
55:
56: if(slen==0)
57: slen=strlen(source);
58: outp=target;
59: inp=source;
60: outend=target+tlen;
61: inend=source+slen;
62: for(;outp<outend && inp<inend;inp++) {
63: working<<=6;
64: i=strchr(base64alphabet,(char)*inp);
65: if(i==NULL) {
66: return(-1);
67: }
68: if(*i=='=') { /* pad char */
69: if((working&0xFF) != 0)
70: return(-1);
71: break;
72: }
73: bits+=6;
74: working |= (i-base64alphabet);
75: if(bits>=8) {
76: *(outp++)=(char)((working&(0xFF<<(bits-8)))>>(bits-8));
77: bits-=8;
78: }
79: }
80: if(outp == outend) {
81: *(--outp)=0;
82: return(-1);
83: }
84: *outp=0;
85: return(outp-target);
86: }
87:
88: static int add_char(char *pos, char ch, int done, char *end)
89: {
90: if(pos>=end) {
91: return(1);
92: }
93: if(done)
94: *pos=base64alphabet[64];
95: else
96: *pos=base64alphabet[(int)ch];
97: return(0);
98: }
99:
100: int b64_encode(char *target, size_t tlen, const char *source, size_t slen) {
101: const char *inp;
102: char *outp;
103: char *outend;
104: const char *inend;
105: char *tmpbuf=NULL;
106: int done=0;
107: char enc;
108: int buf;
109:
110: if(slen==0)
111: slen=strlen(source);
112: inp=source;
113: if(source==target) {
114: tmpbuf=(char *)malloc(tlen);
115: if(tmpbuf==NULL)
116: return(-1);
117: outp=tmpbuf;
118: }
119: else
120: outp=target;
121:
122: outend=outp+tlen;
123: inend=inp+slen;
124: for(;(inp < inend) && !done;) {
125: enc=*(inp++);
126: buf=(enc & 0x03)<<4;
127: enc=(enc&0xFC)>>2;
128: if(add_char(outp++, enc, done, outend)) {
129: FREE_AND_NULL(tmpbuf);
130: return(-1);
131: }
132: enc=buf|((*inp & 0xF0) >> 4);
133: if(add_char(outp++, enc, done, outend)) {
134: FREE_AND_NULL(tmpbuf);
135: return(-1);
136: }
137: if(inp==inend)
138: done=1;
139: buf=(*(inp++)<<2)&0x3C;
140: enc=buf|((*inp & 0xC0)>>6);
141: if(add_char(outp++, enc, done, outend)) {
142: FREE_AND_NULL(tmpbuf);
143: return(-1);
144: }
145: if(inp==inend)
146: done=1;
147: enc=((int)*(inp++))&0x3F;
148: if(add_char(outp++, enc, done, outend)) {
149: FREE_AND_NULL(tmpbuf);
150: return(-1);
151: }
152: if(inp==inend)
153: done=1;
154: }
155: if(outp<outend)
156: *outp=0;
157: if(target==source) {
158: memcpy(target,tmpbuf,tlen);
159: free(tmpbuf);
160: }
161:
162: return(outp-target);
163: }
164:
165: #ifdef BASE64_TEST
166: int main(int argc, char**argv)
167: {
168: int i,j;
169: char buf[512];
170:
171: for(i=1;i<argc;i++) {
172: j=b64_decode(buf,sizeof(buf),argv[i],0);
173: printf("%s (%d)\n",buf,j);
174: }
175:
176: return 0;
177: }
178: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.