Back to index

lightning-sunbird  0.9+nobinonly
nsMsgAppleEncode.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /*
00040  *
00041  *   apple_double_encode.c
00042  *      ---------------------
00043  *
00044  *    The routines doing the Apple Double Encoding.
00045  *            
00046  *                   2aug95 mym    Created.
00047  *            
00048  */
00049 
00050 #include "nscore.h"
00051 #include "msgCore.h"
00052 #include "nsMimeTypes.h"
00053 #include "prprf.h"
00054 
00055 #include "nsMsgAppleDouble.h"
00056 #include "nsMsgAppleCodes.h"
00057 
00058 #if defined(XP_MAC) || defined(XP_MACOSX)
00059 
00060 #include <Errors.h>
00061 
00062 /*
00063 **     Local Functions prototypes.
00064 */
00065 static int output64chunk( appledouble_encode_object* p_ap_encode_obj, 
00066                             int c1, int c2, int c3, int pads);
00067                             
00068 static int to64(appledouble_encode_object* p_ap_encode_obj, 
00069                             char   *p, 
00070                             int    in_size);
00071  
00072 static int finish64(appledouble_encode_object* p_ap_encode_obj);
00073 
00074 
00075 #define BUFF_LEFT(p) ((p)->s_outbuff - (p)->pos_outbuff)       
00076 
00077 /*
00078 **     write_stream.
00079 */
00080 int write_stream(
00081        appledouble_encode_object *p_ap_encode_obj,
00082        char   *out_string,
00083        int           len)                 
00084 {      
00085        if (p_ap_encode_obj->pos_outbuff + len < p_ap_encode_obj->s_outbuff)
00086        {
00087               memcpy(p_ap_encode_obj->outbuff + p_ap_encode_obj->pos_outbuff, 
00088                      out_string, 
00089                      len);
00090               p_ap_encode_obj->pos_outbuff += len;
00091               return noErr;
00092        }
00093        else
00094        {
00095               /*
00096               **     If the buff doesn't have enough space, use the overflow buffer then.
00097               */
00098               int s_len = p_ap_encode_obj->s_outbuff - p_ap_encode_obj->pos_outbuff;
00099               
00100               memcpy(p_ap_encode_obj->outbuff + p_ap_encode_obj->pos_outbuff, 
00101                      out_string, 
00102                      s_len);
00103               memcpy(p_ap_encode_obj->b_overflow + p_ap_encode_obj->s_overflow,
00104                      out_string + s_len,
00105                      p_ap_encode_obj->s_overflow += (len - s_len));
00106               p_ap_encode_obj->pos_outbuff += s_len;
00107               return errEOB;
00108        }
00109 }
00110 
00111 int fill_apple_mime_header(
00112        appledouble_encode_object *p_ap_encode_obj)
00113 {
00114        int  status;
00115        
00116        char tmpstr[266];
00117        
00118 #if 0  
00119 //     strcpy(tmpstr, "Content-Type: multipart/mixed; boundary=\"-\"\n\n---\n");
00120 //     status = write_stream(p_ap_encode_env, 
00121 //                                        tmpstr,
00122 //                                        strlen(tmpstr));
00123 //     if (status != noErr)
00124 //            return status;
00125 
00126        PR_snprintf(tmpstr, sizeof(tmpstr),
00127                      "Content-Type: multipart/appledouble; boundary=\"=\"; name=\"");
00128        status = write_stream(p_ap_encode_obj, 
00129                                           tmpstr,
00130                                           strlen(tmpstr));
00131        if (status != noErr)
00132               return status;
00133               
00134        status = write_stream(p_ap_encode_obj,
00135                                           p_ap_encode_obj->fname,
00136                                           nsCRT::strlen(p_ap_encode_obj->fname));
00137        if (status != noErr)
00138               return status;
00139               
00140        PR_snprintf(tmpstr, sizeof(tmpstr),
00141                      "\"\r\nContent-Disposition: inline; filename=\"%s\"\r\n\r\n\r\n--=\r\n",
00142                      p_ap_encode_obj->fname);
00143 #endif
00144        PR_snprintf(tmpstr, sizeof(tmpstr), "--%s"CRLF, p_ap_encode_obj->boundary);
00145        status = write_stream(p_ap_encode_obj, 
00146                                           tmpstr, 
00147                                           strlen(tmpstr));
00148        return status;
00149 } 
00150 
00151 int ap_encode_file_infor(
00152        appledouble_encode_object *p_ap_encode_obj)
00153 {
00154        CInfoPBRec cipbr;
00155        HFileInfo *fpb = (HFileInfo *)&cipbr;
00156        ap_header     head;
00157        ap_entry      entries[NUM_ENTRIES];
00158        ap_dates      dates;
00159        short         i;
00160        long          comlen;
00161        DateTimeRec cur_time;
00162        unsigned      long cur_secs;
00163        char          comment[256];
00164        Str63         fname;
00165        int                  status;
00166 
00167        strcpy((char *)fname+1,p_ap_encode_obj->fname);
00168        fname[0] = strlen(p_ap_encode_obj->fname);
00169        
00170        fpb->ioNamePtr = fname;
00171        fpb->ioDirID   = p_ap_encode_obj->dirId;
00172        fpb->ioVRefNum = p_ap_encode_obj->vRefNum;
00173        fpb->ioFDirIndex = 0;
00174        if (PBGetCatInfoSync(&cipbr) != noErr) 
00175        {
00176               return errFileOpen;
00177        }
00178 
00179        /* get a file comment, if possible */
00180 #if TARGET_CARBON
00181     // not sure why working directories are needed here...
00182     comlen = 0;
00183 #else
00184        long          procID;
00185        procID = 0;
00186        GetWDInfo(p_ap_encode_obj->vRefNum, &fpb->ioVRefNum, &fpb->ioDirID, &procID);
00187        IOParam       vinfo;
00188        memset((void *) &vinfo, '\0', sizeof (vinfo));
00189        GetVolParmsInfoBuffer vp;
00190        vinfo.ioCompletion  = nil;
00191        vinfo.ioVRefNum      = fpb->ioVRefNum;
00192        vinfo.ioBuffer              = (Ptr) &vp;
00193        vinfo.ioReqCount     = sizeof (vp);
00194        comlen = 0;
00195        if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
00196               ((vp.vMAttrib >> bHasDesktopMgr) & 1)) 
00197        {
00198               DTPBRec       dtp;
00199               memset((void *) &dtp, '\0', sizeof (dtp));
00200               dtp.ioVRefNum = fpb->ioVRefNum;
00201               if (PBDTGetPath(&dtp) == noErr) 
00202               {
00203                      dtp.ioCompletion = nil;
00204                      dtp.ioDTBuffer = (Ptr) comment;
00205                      dtp.ioNamePtr  = fpb->ioNamePtr;
00206                      dtp.ioDirID    = fpb->ioFlParID;
00207                      if (PBDTGetCommentSync(&dtp) == noErr) 
00208                             comlen = dtp.ioDTActCount;
00209               }
00210        }
00211 #endif
00212        
00213        /* write header */
00214 //     head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
00215        head.magic   = APPLEDOUBLE_MAGIC;         /* always do apple double */
00216        head.version = VERSION;
00217        memset(head.fill, '\0', sizeof (head.fill));
00218        head.entries = NUM_ENTRIES - 1;
00219        status = to64(p_ap_encode_obj,
00220                                    (char *) &head,
00221                                    sizeof (head));                           
00222        if (status != noErr)
00223               return status;
00224 
00225        /* write entry descriptors */
00226        entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
00227        entries[0].id        = ENT_NAME;
00228        entries[0].length = *fpb->ioNamePtr;
00229        entries[1].id        = ENT_FINFO;
00230        entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
00231        entries[2].id        = ENT_DATES;
00232        entries[2].length = sizeof (ap_dates);
00233        entries[3].id        = ENT_COMMENT;
00234        entries[3].length = comlen;
00235        entries[4].id        = ENT_RFORK;
00236        entries[4].length = fpb->ioFlRLgLen;
00237        entries[5].id        = ENT_DFORK;
00238        entries[5].length = fpb->ioFlLgLen;
00239 
00240        /* correct the link in the entries. */
00241        for (i = 1; i < NUM_ENTRIES; ++i) 
00242        {
00243               entries[i].offset = entries[i-1].offset + entries[i-1].length;
00244        }
00245        status = to64(p_ap_encode_obj,
00246                                    (char *) entries,
00247                                    sizeof (ap_entry) * head.entries); 
00248        if (status != noErr)
00249               return status;
00250 
00251        /* write name */
00252        status = to64(p_ap_encode_obj,
00253                                    (char *) fpb->ioNamePtr + 1,
00254                                    *fpb->ioNamePtr); 
00255        if (status != noErr)
00256               return status;
00257        
00258        /* write finder info */
00259        status = to64(p_ap_encode_obj,
00260                                    (char *) &fpb->ioFlFndrInfo,
00261                                    sizeof (FInfo));
00262        if (status != noErr)
00263               return status;
00264                                      
00265        status = to64(p_ap_encode_obj,
00266                                    (char *) &fpb->ioFlXFndrInfo,
00267                                    sizeof (FXInfo));
00268        if (status != noErr)
00269               return status;
00270 
00271        /* write dates */
00272        GetTime(&cur_time);
00273        DateToSeconds(&cur_time, &cur_secs);
00274        dates.create = fpb->ioFlCrDat + CONVERT_TIME;
00275        dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
00276        dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
00277        dates.access = cur_secs + CONVERT_TIME;
00278        status = to64(p_ap_encode_obj,
00279                                    (char *) &dates,
00280                                    sizeof (ap_dates)); 
00281        if (status != noErr)
00282               return status;
00283        
00284        /* write comment */
00285        if (comlen)
00286        {
00287               status = to64(p_ap_encode_obj,
00288                                    comment,
00289                                    comlen * sizeof(char));
00290        }
00291        /*
00292        **     Get some help information on deciding the file type.
00293        */
00294        if (fpb->ioFlFndrInfo.fdType == 'TEXT' || fpb->ioFlFndrInfo.fdType == 'text')
00295        {
00296               p_ap_encode_obj->text_file_type = true;
00297        }
00298        
00299        return status;       
00300 }
00301 /*
00302 **     ap_encode_header
00303 **
00304 **            encode the file header and the resource fork.
00305 **
00306 */
00307 int ap_encode_header(
00308        appledouble_encode_object* p_ap_encode_obj, 
00309        PRBool  firstime)
00310 {
00311        Str255        name;
00312        char          rd_buff[256];
00313        short   fileId;
00314        OSErr  retval = noErr;
00315        int           status;
00316        long   inCount;
00317        
00318        if (firstime)
00319        {
00320     PL_strcpy(rd_buff, 
00321                      "Content-Type: application/applefile\r\nContent-Transfer-Encoding: base64\r\n\r\n");
00322               status = write_stream(p_ap_encode_obj,
00323                                                  rd_buff, 
00324                                                  strlen(rd_buff)); 
00325               if (status != noErr)
00326                      return status;
00327                      
00328               status = ap_encode_file_infor(p_ap_encode_obj); 
00329               if (status != noErr)
00330                      return status;
00331               
00332               /*
00333               ** preparing to encode the resource fork.
00334               */
00335               name[0] = strlen(p_ap_encode_obj->fname);
00336               strcpy((char *)name+1, p_ap_encode_obj->fname);
00337               if (HOpenRF(p_ap_encode_obj->vRefNum, p_ap_encode_obj->dirId,
00338                                    name, fsRdPerm,
00339                                    &p_ap_encode_obj->fileId) != noErr)
00340               {
00341                      return errFileOpen;                
00342               }
00343        }
00344 
00345        fileId = p_ap_encode_obj->fileId;
00346        while (retval == noErr)
00347        {
00348               if (BUFF_LEFT(p_ap_encode_obj) < 400)
00349                      break;
00350                      
00351               inCount = 256;
00352               retval = FSRead(fileId, &inCount, rd_buff);
00353               if (inCount)
00354               {
00355                      status = to64(p_ap_encode_obj,
00356                                                  rd_buff,
00357                                                  inCount);
00358                      if (status != noErr)
00359                             return status;
00360               }
00361        }
00362        
00363        if (retval == eofErr)
00364        {
00365               FSClose(fileId);
00366 
00367               status = finish64(p_ap_encode_obj);
00368               if (status != noErr)
00369                      return status;
00370               
00371               /*
00372               ** write out the boundary 
00373               */
00374               PR_snprintf(rd_buff, sizeof(rd_buff),
00375                                           CRLF"--%s"CRLF, 
00376                                           p_ap_encode_obj->boundary);
00377                                    
00378               status = write_stream(p_ap_encode_obj,
00379                                           rd_buff,
00380                                           strlen(rd_buff));
00381               if (status == noErr)
00382                      status = errDone;
00383        }
00384        return status;
00385 }
00386 
00387 static void replace(char *p, int len, char frm, char to)
00388 {
00389        for (; len > 0; len--, p++)
00390               if (*p == frm)       *p = to;
00391 }
00392 
00393 /* Description of the various file formats and their magic numbers           */
00394 struct magic 
00395 {
00396     char      *name;               /* Name of the file format                              */
00397     char      *num;                /* The magic number                                     */
00398     int       len;                 /* Length (0 means strlen(magicnum))             */
00399 };
00400 
00401 /* The magic numbers of the file formats we know about */
00402 static struct magic magic[] = 
00403 {
00404     { "image/gif",   "GIF",                        0 },
00405     { "image/jpeg", "\377\330\377",   0 },
00406     { "video/mpeg", "\0\0\001\263",         4 },
00407     { "application/postscript", "%!", 0 },
00408 };
00409 static int    num_magic = (sizeof(magic)/sizeof(magic[0]));
00410 
00411 static char *text_type    = TEXT_PLAIN;                               /* the text file type.      */            
00412 static char *default_type = APPLICATION_OCTET_STREAM;
00413 
00414 
00415 /*
00416  * Determins the format of the file "inputf".  The name
00417  * of the file format (or NULL on error) is returned.
00418  */
00419 static char *magic_look(char *inbuff, int numread)
00420 {
00421     int i, j;
00422 
00423        for (i=0; i<num_magic; i++) 
00424        {
00425               if (magic[i].len == 0) 
00426                      magic[i].len = strlen(magic[i].num);
00427        }
00428 
00429     for (i=0; i<num_magic; i++) 
00430     {
00431               if (numread >= magic[i].len) 
00432               {
00433               for (j=0; j<magic[i].len; j++) 
00434               {
00435                             if (inbuff[j] != magic[i].num[j]) break;
00436               }
00437               
00438               if (j == magic[i].len) 
00439                      return magic[i].name;
00440               }
00441     }
00442 
00443     return default_type;
00444 }
00445 /*
00446 **     ap_encode_data
00447 **
00448 **     ---------------
00449 **
00450 **            encode on the data fork.
00451 **
00452 */
00453 int ap_encode_data(
00454        appledouble_encode_object* p_ap_encode_obj, 
00455        PRBool firstime)
00456 {
00457        Str255        name;
00458        char                 rd_buff[256];
00459        short         fileId;
00460        OSErr         retval = noErr;
00461        long          in_count;
00462        int                  status;
00463        
00464        if (firstime)
00465        {      
00466               char* magic_type;
00467                      
00468               /*
00469               ** preparing to encode the data fork.
00470               */
00471               name[0] = strlen(p_ap_encode_obj->fname);
00472     PL_strcpy((char*)name+1, p_ap_encode_obj->fname);
00473               if (HOpen(    p_ap_encode_obj->vRefNum,
00474                                    p_ap_encode_obj->dirId, 
00475                                    name, 
00476                                    fsRdPerm, 
00477                                    &fileId) != noErr)
00478               {
00479                      return errFileOpen;
00480               }
00481               p_ap_encode_obj->fileId = fileId;
00482                      
00483               
00484               if (!p_ap_encode_obj->text_file_type)
00485               {      
00486       /*
00487       **      do a smart check for the file type.
00488       */
00489       in_count = 256;
00490       retval   = FSRead(fileId, &in_count, rd_buff);
00491       magic_type = magic_look(rd_buff, in_count);
00492       
00493       /* don't forget to rewind the index to start point. */ 
00494       SetFPos(fileId, fsFromStart, 0L);
00495       /* and reset retVal just in case... */
00496       if (retval == eofErr)
00497         retval = noErr;
00498               }
00499               else
00500               {
00501                      magic_type = text_type;            /* we already know it is a text type.     */
00502               }
00503 
00504               /*
00505               **     the data portion header information.
00506               */
00507               PR_snprintf(rd_buff, sizeof(rd_buff),
00508                      "Content-Type: %s; name=\"%s\"" CRLF "Content-Transfer-Encoding: base64" CRLF "Content-Disposition: inline; filename=\"%s\""CRLF CRLF,
00509                      magic_type,
00510                      p_ap_encode_obj->fname,
00511                      p_ap_encode_obj->fname);
00512                      
00513               status = write_stream(p_ap_encode_obj, 
00514                                    rd_buff, 
00515                                    strlen(rd_buff)); 
00516               if (status != noErr)
00517                      return status;
00518        }
00519        
00520        while (retval == noErr)
00521        {
00522               if (BUFF_LEFT(p_ap_encode_obj) < 400)
00523                      break;
00524                      
00525               in_count = 256;
00526               retval = FSRead(p_ap_encode_obj->fileId, 
00527                                           &in_count, 
00528                                           rd_buff);
00529               if (in_count)
00530               {
00531 /*                   replace(rd_buff, in_count, '\r', '\n');                                             */
00532 /* ** may be need to do character set conversion here for localization.      **  */        
00533                      status = to64(p_ap_encode_obj,
00534                                           rd_buff,
00535                                           in_count);
00536                      if (status != noErr)
00537                             return status;
00538               }
00539        }
00540        
00541        if (retval == eofErr)
00542        {
00543               FSClose(p_ap_encode_obj->fileId);
00544 
00545               status = finish64(p_ap_encode_obj);
00546               if (status != noErr)
00547                      return status;
00548               
00549               /* write out the boundary   */
00550               
00551               PR_snprintf(rd_buff, sizeof(rd_buff),
00552                                           CRLF"--%s--"CRLF CRLF, 
00553                                           p_ap_encode_obj->boundary);
00554        
00555               status = write_stream(p_ap_encode_obj,
00556                                           rd_buff,
00557                                           strlen(rd_buff));
00558        
00559               if (status == noErr)                      
00560                      status = errDone;
00561        }
00562        return status;
00563 }
00564 
00565 static char basis_64[] =
00566    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00567 
00568 /* 
00569 **     convert the stream in the inbuff to 64 format and put it in the out buff.
00570 **  To make the life easier, the caller will responcable of the cheking of the outbuff's bundary.
00571 */
00572 static int 
00573 to64(appledouble_encode_object* p_ap_encode_obj, 
00574        char   *p, 
00575        int    in_size) 
00576 {
00577        int    status;
00578     int c1, c2, c3, ct;
00579     unsigned char *inbuff = (unsigned char*)p;
00580     
00581        ct = p_ap_encode_obj->ct;                 /* the char count left last time. */
00582        
00583        /*
00584        **      resume the left state of the last conversion.
00585        */
00586        switch (p_ap_encode_obj->state64)
00587        {
00588               case 0:
00589                      p_ap_encode_obj->c1 = c1 = *inbuff ++;
00590                      if (--in_size <= 0)
00591                      {
00592                             p_ap_encode_obj->state64 = 1;
00593                             return noErr;
00594                      }
00595                      p_ap_encode_obj->c2 = c2 = *inbuff ++;
00596                      if (--in_size <= 0)
00597                      {
00598                             p_ap_encode_obj->state64 = 2;
00599                             return noErr;
00600                      }
00601                      c3 = *inbuff ++;            --in_size;
00602                      break;
00603               case 1:
00604                      c1 = p_ap_encode_obj->c1;
00605                      p_ap_encode_obj->c2 = c2 = *inbuff ++;
00606                      if (--in_size <= 0)
00607                      {
00608                             p_ap_encode_obj->state64 = 2;
00609                             return noErr;
00610                      }
00611                      c3 = *inbuff ++;            --in_size;
00612                      break;
00613               case 2:
00614                      c1 = p_ap_encode_obj->c1;
00615                      c2 = p_ap_encode_obj->c2;
00616                      c3 = *inbuff ++;            --in_size;
00617                      break;
00618        }
00619        
00620     while (in_size >= 0) 
00621     {
00622        status = output64chunk(p_ap_encode_obj, 
00623                                                  c1, 
00624                                                  c2, 
00625                                                  c3, 
00626                                                  0);
00627        if (status != noErr)
00628               return status;
00629               
00630        ct += 4;
00631         if (ct > 71) 
00632         { 
00633               status = write_stream(p_ap_encode_obj, 
00634                                                  CRLF, 
00635                                                  2);
00636               if (status != noErr)
00637                      return status;
00638                      
00639             ct = 0;
00640         }
00641 
00642               if (in_size <= 0)
00643               {
00644                      p_ap_encode_obj->state64 = 0;
00645                      break;
00646               }
00647               
00648               c1 = (int)*inbuff++;
00649               if (--in_size <= 0)
00650               {
00651                      p_ap_encode_obj->c1 = c1;
00652                      p_ap_encode_obj->state64 = 1;
00653                      break;
00654               }
00655               c2 = *inbuff++;
00656               if (--in_size <= 0)
00657               {
00658                      p_ap_encode_obj->c1   = c1;
00659                      p_ap_encode_obj->c2   = c2;
00660                      p_ap_encode_obj->state64 = 2;
00661                      break;
00662               }
00663               c3 = *inbuff++;
00664               in_size--;
00665     }
00666     p_ap_encode_obj->ct = ct;
00667     return status;
00668 }
00669 
00670 /*
00671 ** clear the left base64 encodes.
00672 */
00673 static int 
00674 finish64(appledouble_encode_object* p_ap_encode_obj)
00675 {
00676        int status;
00677        
00678        switch (p_ap_encode_obj->state64)
00679        {
00680               case 0:
00681                      break;
00682               case 1:
00683                      status = output64chunk(p_ap_encode_obj, 
00684                                                                p_ap_encode_obj->c1, 
00685                                                                0, 
00686                                                                0, 
00687                                                                2);
00688                      break;
00689               case 2:
00690                      status = output64chunk(p_ap_encode_obj, 
00691                                                                p_ap_encode_obj->c1, 
00692                                                                p_ap_encode_obj->c2, 
00693                                                                0, 
00694                                                                1);
00695                      break;
00696        }
00697        status = write_stream(p_ap_encode_obj, CRLF, 2);
00698        p_ap_encode_obj->state64 = 0;
00699        p_ap_encode_obj->ct          = 0;
00700        return status;
00701 }
00702 
00703 static int output64chunk(
00704        appledouble_encode_object* p_ap_encode_obj, 
00705        int c1, int c2, int c3, int pads)
00706 {
00707        char tmpstr[32];
00708        char *p = tmpstr;
00709        
00710     *p++ = basis_64[c1>>2];
00711     *p++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
00712     if (pads == 2) 
00713     {
00714         *p++ = '=';
00715         *p++ = '=';
00716     } 
00717     else if (pads) 
00718     {
00719         *p++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
00720         *p++ = '=';
00721     } 
00722     else 
00723     {
00724         *p++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
00725         *p++ = basis_64[c3 & 0x3F];
00726     }
00727        return write_stream(p_ap_encode_obj,
00728                                           tmpstr,
00729                                           p-tmpstr);
00730 }
00731 
00732 #endif               /* if define XP_MAC */