base64.c

Go to the documentation of this file.
00001 
00002 /*  $Id: base64.c 410 2005-01-24 02:22:13Z terry_teague $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "lang.h"
00033 #include "BASE64.H"
00034 
00035 
00036 static char encodingTable [64] = {
00037 
00038     'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
00039     
00040     'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
00041     
00042     'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
00043     
00044     'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
00045     };
00046 
00047 
00048 static unsigned char gethandlechar (Handle h, unsigned long ix) {
00049 
00050     return ((*h) [ix]);
00051     } /*gethandlechar*/
00052 
00053 
00054 static void sethandlechar (Handle h, unsigned long ix, unsigned char ch) {
00055 
00056     (*h) [ix] = ch;
00057     } /*sethandlechar*/
00058 
00059 
00060 #define new_base64 1
00061 
00062 #ifdef new_base64
00063 
00064 boolean base64encodehandle (Handle htext, Handle h64, short linelength) { 
00065 
00066     /*
00067     encode the handle. some funny stuff about linelength -- it only makes
00068     sense to make it a multiple of 4. if it's not a multiple of 4, we make it
00069     so (by only checking it every 4 characters. 
00070 
00071     further, if it's 0, we don't add any line breaks at all.
00072 
00073     5.0a18 dmb: line breaks are /r, not /n
00074     
00075     6.1d4 AR: updated to grow h64 in one go instead of once for every
00076     three bytes of htext.
00077     */
00078 
00079     unsigned long ixtext;
00080     unsigned long lentext;
00081     unsigned long len64;
00082     unsigned long pos64 = 0;
00083     long ctremaining;
00084     unsigned char inbuf [3], outbuf [4];
00085     short i;
00086     short charsonline = 0, ctcopy;
00087     
00088     ixtext = 0;
00089 
00090     lentext = gethandlesize (htext);
00091     
00092     len64 = (lentext / 3) * 4;
00093     
00094     if (lentext % 3 > 0)
00095         len64 += 4;
00096     
00097     if (linelength > 0) { /* add room for linebreaks */
00098         
00099         unsigned long ctquadruplets = linelength / 4;
00100         
00101         if (linelength % 4 > 0)
00102             ++ctquadruplets;
00103         
00104         linelength = ctquadruplets * 4;
00105             
00106         len64 += (len64 / linelength);
00107         }
00108 
00109     if (!sethandlesize (h64, len64))
00110         return (false);
00111 
00112     while (true) {
00113 
00114         ctremaining = lentext - ixtext;
00115     
00116         if (ctremaining <= 0)
00117             break;
00118                 
00119         for (i = 0; i < 3; i++) { 
00120         
00121             unsigned long ix = ixtext + i;
00122         
00123             if (ix < lentext)
00124                 inbuf [i] = gethandlechar (htext, ix);
00125             else
00126                 inbuf [i] = 0;
00127             } /*for*/
00128         
00129         outbuf [0] = (inbuf [0] & 0xFC) >> 2;
00130     
00131         outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
00132     
00133         outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
00134         
00135         outbuf [3] = inbuf [2] & 0x3F;
00136         
00137         ctcopy = 4;
00138     
00139         switch (ctremaining) {
00140         
00141             case 1: 
00142                 ctcopy = 2; 
00143             
00144                 break;
00145         
00146             case 2: 
00147                 ctcopy = 3; 
00148             
00149                 break;
00150             } /*switch*/
00151 
00152         for (i = 0; i < ctcopy; i++)
00153             sethandlechar (h64, pos64 + i, encodingTable [outbuf [i]]);
00154         
00155         for (i = ctcopy; i < 4; i++)
00156             sethandlechar (h64, pos64 + i, '=');
00157         
00158         ixtext += 3;
00159     
00160         charsonline += 4;
00161         
00162         pos64 += 4;
00163     
00164         if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
00165     
00166             if (charsonline >= linelength) {
00167             
00168                 charsonline = 0;
00169                 
00170                 sethandlechar (h64, pos64++, '\r');
00171                 }
00172             }
00173         } /*while*/
00174 
00175     assert (pos64 == len64); /*there's a bug in here if this assertion doesn't hold*/
00176 
00177     return (true);
00178     } /*encodehandle*/
00179 
00180 #elif
00181 
00182 boolean base64encodehandle (Handle htext, Handle h64, short linelength) { 
00183 
00184     /*
00185     encode the handle. some funny stuff about linelength -- it only makes
00186     sense to make it a multiple of 4. if it's not a multiple of 4, we make it
00187     so (by only checking it every 4 characters. 
00188 
00189     further, if it's 0, we don't add any line breaks at all.
00190 
00191     5.0a18 dmb: line breaks are /r, not /n
00192     */
00193 
00194     unsigned long ixtext;
00195     unsigned long lentext;
00196     unsigned long origsize;
00197     long ctremaining;
00198     unsigned char inbuf [3], outbuf [4];
00199     short i;
00200     short charsonline = 0, ctcopy;
00201     
00202     ixtext = 0;
00203 
00204     lentext = gethandlesize (htext);
00205 
00206     while (true) {
00207 
00208         ctremaining = lentext - ixtext;
00209     
00210         if (ctremaining <= 0)
00211             break;
00212                 
00213         for (i = 0; i < 3; i++) { 
00214         
00215             unsigned long ix = ixtext + i;
00216         
00217             if (ix < lentext)
00218                 inbuf [i] = gethandlechar (htext, ix);
00219             else
00220                 inbuf [i] = 0;
00221             } /*for*/
00222         
00223         outbuf [0] = (inbuf [0] & 0xFC) >> 2;
00224     
00225         outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
00226     
00227         outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
00228         
00229         outbuf [3] = inbuf [2] & 0x3F;
00230     
00231         origsize = gethandlesize (h64);
00232     
00233         if (!sethandlesize (h64, origsize + 4))
00234             return (false);
00235         
00236         ctcopy = 4;
00237     
00238         switch (ctremaining) {
00239         
00240             case 1: 
00241                 ctcopy = 2; 
00242             
00243                 break;
00244         
00245             case 2: 
00246                 ctcopy = 3; 
00247             
00248                 break;
00249             } /*switch*/
00250 
00251         for (i = 0; i < ctcopy; i++)
00252             sethandlechar (h64, origsize + i, encodingTable [outbuf [i]]);
00253         
00254         for (i = ctcopy; i < 4; i++)
00255             sethandlechar (h64, origsize + i, '=');
00256         
00257         ixtext += 3;
00258     
00259         charsonline += 4;
00260     
00261         if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
00262     
00263             if (charsonline >= linelength) {
00264             
00265                 charsonline = 0;
00266             
00267                 origsize = gethandlesize (h64);
00268             
00269                 if (!sethandlesize (h64, origsize + 1))
00270                     return (false);
00271                 
00272                 sethandlechar (h64, origsize, '\r');
00273                 }
00274             }
00275         } /*while*/
00276 
00277     return (true);
00278     } /*encodehandle*/
00279 
00280 #endif
00281 
00282 
00283 #ifdef new_base64
00284 
00285 boolean base64decodehandle (Handle h64, Handle htext) {
00286 
00287     unsigned long ixtext;
00288     unsigned long lentext;
00289     unsigned char ch;
00290     unsigned char inbuf [4], outbuf [3];
00291     short ixinbuf;
00292     boolean flendtext = false;
00293     handlestream s;
00294     
00295     ixtext = 0;
00296 
00297     lentext = gethandlesize (h64);
00298 
00299     ixinbuf = 0;
00300     
00301     openhandlestream (htext, &s);
00302 
00303     while (true) {
00304         short ctcharsinbuf = 3;
00305 
00306         if (ixtext >= lentext)
00307             break;
00308         
00309         ch = gethandlechar (h64, ixtext++);
00310     
00311         if ((ch >= 'A') && (ch <= 'Z'))
00312             ch = ch - 'A';
00313     
00314         else if ((ch >= 'a') && (ch <= 'z'))
00315             ch = ch - 'a' + 26;
00316         
00317         else if ((ch >= '0') && (ch <= '9'))
00318             ch = ch - '0' + 52;
00319     
00320         else if (ch == '+')
00321             ch = 62;
00322         
00323         else if (ch == '/')
00324             ch = 63;
00325 
00326         else if (ch == '=') /*no op -- can't ignore this one*/
00327             flendtext = true;
00328     
00329         else
00330             continue; 
00331          
00332         if (flendtext) {
00333         
00334             if (ixinbuf == 0)
00335                 break;
00336             
00337             if ((ixinbuf == 1) || (ixinbuf == 2))
00338                 ctcharsinbuf = 1;
00339             else
00340                 ctcharsinbuf = 2;
00341         
00342             ixinbuf = 3;
00343             }
00344     
00345         inbuf [ixinbuf++] = ch;
00346     
00347         if (ixinbuf == 4) {
00348         
00349             ixinbuf = 0;
00350         
00351             outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
00352         
00353             outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
00354         
00355             outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
00356 
00357             if (!writehandlestream (&s, outbuf, ctcharsinbuf))
00358                 return (false);
00359             }
00360     
00361         if (flendtext)
00362             break;
00363         } /*while*/
00364     
00365     closehandlestream (&s);
00366     
00367     return (true);
00368     } /*decodehandle*/
00369 
00370 #elif
00371 
00372 boolean base64decodehandle (Handle h64, Handle htext) {
00373 
00374     unsigned long ixtext;
00375     unsigned long lentext;
00376     unsigned long origsize;
00377     unsigned char ch;
00378     unsigned char inbuf [4], outbuf [3];
00379     short i, ixinbuf;
00380     boolean flignore;
00381     boolean flendtext = false;
00382     
00383     ixtext = 0;
00384 
00385     lentext = gethandlesize (h64);
00386 
00387     ixinbuf = 0;
00388 
00389     while (true) {
00390     
00391         if (ixtext >= lentext)
00392             break;
00393         
00394         ch = gethandlechar (h64, ixtext++);
00395     
00396         flignore = false;
00397     
00398         if ((ch >= 'A') && (ch <= 'Z'))
00399             ch = ch - 'A';
00400     
00401         else if ((ch >= 'a') && (ch <= 'z'))
00402             ch = ch - 'a' + 26;
00403         
00404         else if ((ch >= '0') && (ch <= '9'))
00405             ch = ch - '0' + 52;
00406     
00407         else if (ch == '+')
00408             ch = 62;
00409         
00410         else if (ch == '=') /*no op -- can't ignore this one*/
00411             flendtext = true;
00412         
00413         else if (ch == '/')
00414             ch = 63;
00415     
00416         else
00417             flignore = true; 
00418     
00419         if (!flignore) {
00420     
00421             short ctcharsinbuf = 3;
00422             boolean flbreak = false;
00423              
00424             if (flendtext) {
00425             
00426                 if (ixinbuf == 0)
00427                     break;
00428                 
00429                 if ((ixinbuf == 1) || (ixinbuf == 2))
00430                     ctcharsinbuf = 1;
00431                 else
00432                     ctcharsinbuf = 2;
00433             
00434                 ixinbuf = 3;
00435             
00436                 flbreak = true;
00437                 }
00438         
00439             inbuf [ixinbuf++] = ch;
00440         
00441             if (ixinbuf == 4) {
00442             
00443                 ixinbuf = 0;
00444             
00445                 outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
00446             
00447                 outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
00448             
00449                 outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
00450     
00451                 origsize = gethandlesize (htext);
00452             
00453                 if (!sethandlesize (htext, origsize + ctcharsinbuf))
00454                     return (false);
00455     
00456                 for (i = 0; i < ctcharsinbuf; i++) 
00457                     sethandlechar (htext, origsize + i, outbuf [i]);
00458                 }
00459         
00460             if (flbreak)
00461                 break;
00462             }
00463         } /*while*/
00464 
00465     return (true);
00466     } /*decodehandle*/
00467 
00468 #endif
00469 
00470 
00471 boolean base64encodeverb (hdltreenode hparam1, tyvaluerecord *vreturned) {
00472 
00473     Handle h64, htext;
00474     short linelength;
00475 
00476     if (!gettextvalue (hparam1, 1, &htext))
00477         return (false);
00478     
00479     flnextparamislast = true;
00480     
00481     if (!getintvalue (hparam1, 2, &linelength))
00482         return (false);
00483 
00484     if (!newemptyhandle (&h64))
00485         return (false);
00486     
00487     if (!base64encodehandle (htext, h64, linelength)) {
00488 
00489         disposehandle (h64);
00490 
00491         return (false);
00492         }
00493     
00494     return (setheapvalue (h64, stringvaluetype, vreturned));
00495     } /*base64encodeverb*/
00496 
00497 
00498 boolean base64decodeverb (hdltreenode hparam1, tyvaluerecord *vreturned) {
00499     
00500     /*
00501     5.0.1 dmb: return a string, not an unknown binary type
00502     */
00503 
00504     Handle h64, htext;
00505     
00506     flnextparamislast = true;
00507     
00508     if (!gettextvalue (hparam1, 1, &h64))
00509         return (false);
00510     
00511     if (!newemptyhandle (&htext))
00512         return (false);
00513     
00514     if (!base64decodehandle (h64, htext)) {
00515         
00516         disposehandle (htext);
00517         
00518         return (false);
00519         }
00520     
00521     return (setheapvalue (htext, stringvaluetype, vreturned));
00522     } /*base64decodeverb*/
00523 
00524 

Generated on Wed May 31 18:19:44 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6