version 1.5, 2002/02/08 17:13:14
|
version 1.25, 2006/01/30 16:16:46
|
|
|
//%///////////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001 BMC Software, Hewlett-Packard Company, IBM, |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// The Open Group, Tivoli Systems |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
|
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation, The Open Group. |
|
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// | // |
// Author: Karl Schopmeyer (k.schopmeyer@opengroup.org) | // Author: Karl Schopmeyer (k.schopmeyer@opengroup.org) |
// | // |
// Modified By: |
// Modified By: David Dillard, VERITAS Software Corp. |
|
// (david.dillard@veritas.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include "Base64.h" | #include "Base64.h" |
#include <cassert> |
#include <Pegasus/Common/ArrayInternal.h> |
#include <strstream> |
|
#include <string> |
|
#include <Pegasus/Common/String.h> |
|
#include <Pegasus/Common/Base64.h> |
|
#include <Pegasus/Common/Array.h> |
|
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
|
|
#define inline | #define inline |
#endif | #endif |
| |
|
|
|
//********************************************************** |
|
/* Encode thanslates one six-bit pattern into a base-64 character. |
|
Unsigned char is used to represent a six-bit stream of date. |
|
|
|
*/ |
|
inline PEGASUS_COMMON_LINKAGE char Base64::_Encode(Uint8 uc) |
|
{ |
|
if (uc < 26) |
|
return 'A'+uc; |
|
|
|
if (uc < 52) |
|
return 'a'+(uc-26); |
|
|
|
if (uc < 62) |
|
return '0'+(uc-52); |
|
|
|
if (uc == 62) |
|
return '+'; |
|
|
|
return '/'; |
|
}; |
|
|
|
//Helper function returns true is a character is a valid base-64 character and false otherwise. |
|
|
|
inline Boolean Base64::_IsBase64(char c) |
|
{ |
|
|
|
if (c >= 'A' && c <= 'Z') |
|
return true; |
|
|
|
if (c >= 'a' && c <= 'z') |
|
return true; |
|
|
|
if (c >= '0' && c <= '9') |
|
return true; |
|
|
|
if (c == '+') |
|
return true; |
|
|
|
if (c == '/') |
|
return true; |
|
|
|
if (c == '=') |
|
return true; |
|
|
|
return false; |
|
}; |
|
|
|
// Translate one base-64 character into a six bit pattern |
|
inline Uint8 Base64::_Decode(char c) |
|
{ |
|
if (c >= 'A' && c <= 'Z') |
|
return c - 'A'; |
|
if (c >= 'a' && c <= 'z') |
|
return c - 'a' + 26; |
|
|
|
if (c >= '0' && c <= '9') |
|
return c - '0' + 52; |
|
|
|
if (c == '+') |
|
return 62; |
|
|
|
return 63; |
|
}; |
|
|
|
|
//************************************************************* | //************************************************************* |
/* Encode static method takes an array of 8-bit values and | /* Encode static method takes an array of 8-bit values and |
returns a base-64 stream. | returns a base-64 stream. |
|
|
implementation and could be improved if it is required for | implementation and could be improved if it is required for |
production. Today it is only for test programs. | production. Today it is only for test programs. |
*/ | */ |
Array<Sint8> Base64::encode(const Array<Uint8>& vby) |
Buffer Base64::encode(const Buffer& vby) |
{ | { |
Array<Sint8> retArray; |
Buffer retArray; |
// If nothing in input string, return empty string | // If nothing in input string, return empty string |
if (vby.size() == 0) | if (vby.size() == 0) |
return retArray; | return retArray; |
// for every character in the input array taken 3 bytes at a time | // for every character in the input array taken 3 bytes at a time |
|
|
for (Uint32 i=0; i < vby.size(); i+=3) | for (Uint32 i=0; i < vby.size(); i+=3) |
{ | { |
| |
|
|
else | else |
retArray.append('='); | retArray.append('='); |
| |
|
|
if (i+2<vby.size()) | if (i+2<vby.size()) |
retArray.append( _Encode(by7)); | retArray.append( _Encode(by7)); |
else | else |
retArray.append('='); | retArray.append('='); |
| |
|
/* ATTN: Need to fix this. It adds unwanted cr-lf after 4 chars. |
|
|
if (i % (76/4*3) == 0) | if (i % (76/4*3) == 0) |
{ | { |
retArray.append( '\r'); | retArray.append( '\r'); |
retArray.append( '\n'); | retArray.append( '\n'); |
} | } |
|
*/ |
}; | }; |
| |
return retArray; | return retArray; |
}; | }; |
/*I checked for the zero length. The algorithm would also work for zero length input stream, but I’m pretty adamant about handling border conditions. They are often the culprits of run-time production failures. | /*I checked for the zero length. The algorithm would also work for zero length input stream, but I’m pretty adamant about handling border conditions. They are often the culprits of run-time production failures. |
The algorithm goes thru each three bytes of data at a time. The first thing I do is to shift the bits around from three 8-bit values to four 6-bit values. Then I encode the 6-bit values and add then one at a time to the output stream. This is actually quite inefficient. The STL character array is being allocated one byte at a time. The algorithm would be much faster, if I pre-allocated that array. I’ll leave that as an optimization practical exercise for the reader. | The algorithm goes thru each three bytes of data at a time. The first thing I do is to shift the bits around from three 8-bit values to four 6-bit values. Then I encode the 6-bit values and add then one at a time to the output stream. This is actually quite inefficient. The STL character array is being allocated one byte at a time. The algorithm would be much faster, if I pre-allocated that array. I’ll leave that as an optimization practical exercise for the reader. |
|
*/ |
| |
/* The decode static method takes a base-64 stream and converts it | /* The decode static method takes a base-64 stream and converts it |
to an array of 8-bit values. | to an array of 8-bit values. |
*/ | */ |
Array<Uint8> Base64::decode(const Array<Sint8> strInput) |
Buffer Base64::decode(const Buffer& strInput) |
{ | { |
//Strip any non-base64 characters from the input | //Strip any non-base64 characters from the input |
PEGASUS_STD(string) str; |
Buffer str; |
for (Uint32 j=0;j<strInput.size();j++) | for (Uint32 j=0;j<strInput.size();j++) |
{ | { |
if (_IsBase64(strInput[j])) | if (_IsBase64(strInput[j])) |
str += strInput[j]; |
str.append(strInput[j]); |
} | } |
| |
Array<Uint8> retArray; |
Buffer retArray; |
| |
// Return if the input is zero length | // Return if the input is zero length |
if (str.length() == 0) |
if (str.size() == 0) |
return retArray; | return retArray; |
| |
// comment | // comment |
for (int i=0; i < str.length();i+=4) |
for (Uint32 i=0; i < str.size(); i+=4) |
{ | { |
char c1='A',c2='A',c3='A',c4='A'; | char c1='A',c2='A',c3='A',c4='A'; |
| |
c1 = str[i]; | c1 = str[i]; |
if (i+1<str.length()) |
if (i+1<str.size()) |
c2 = str[i+1]; | c2 = str[i+1]; |
if (i+2<str.length()) |
if (i+2<str.size()) |
c3 = str[i+2]; | c3 = str[i+2]; |
if (i+3<str.length()) |
if (i+3<str.size()) |
c4 = str[i+3]; | c4 = str[i+3]; |
| |
Uint8 by1=0,by2=0,by3=0,by4=0; | Uint8 by1=0,by2=0,by3=0,by4=0; |
|
|
// " 4 " << c4 << " " << by4 << endl; | // " 4 " << c4 << " " << by4 << endl; |
| |
// append first byte by shifting | // append first byte by shifting |
retArray.append( (by1<<2)|(by2>>4) ); |
retArray.append( static_cast<char>((by1<<2)|(by2>>4)) ); |
| |
// append second byte if not padding | // append second byte if not padding |
if (c3 != '=') | if (c3 != '=') |
retArray.append( ((by2&0xf)<<4)|(by3>>2) ); |
retArray.append( static_cast<char>(((by2&0xf)<<4)|(by3>>2)) ); |
| |
if (c4 != '=') | if (c4 != '=') |
retArray.append( ((by3&0x3)<<6)|by4 ); |
retArray.append( static_cast<char>(((by3&0x3)<<6)|by4) ); |
} | } |
| |
return retArray; |
|
}; |
|
|
|
//********************************************************** |
|
/* Encode thanslates one six-bit pattern into a base-64 character. |
|
Unsigned char is used to represent a six-bit stream of date. |
|
|
|
*/ |
|
inline PEGASUS_COMMON_LINKAGE char Base64::_Encode(Uint8 uc) |
|
{ |
|
if (uc < 26) |
|
return 'A'+uc; |
|
|
|
if (uc < 52) |
|
return 'a'+(uc-26); |
|
|
|
if (uc < 62) |
|
return '0'+(uc-52); |
|
|
|
if (uc == 62) |
|
return '+'; |
|
|
|
return '/'; |
|
}; |
|
|
|
//Helper function returns true is a character is a valid base-64 character and false otherwise. |
|
|
|
inline Boolean Base64::_IsBase64(char c) |
|
{ |
|
|
|
if (c >= 'A' && c <= 'Z') |
|
return true; |
|
|
|
if (c >= 'a' && c <= 'z') |
|
return true; |
|
|
|
if (c >= '0' && c <= '9') |
|
return true; |
|
|
|
if (c == '+') |
|
return true; |
|
|
|
if (c == '/') |
|
return true; |
|
|
|
if (c == '=') |
|
return true; |
|
|
|
return false; |
|
}; |
|
| |
// Translate one base-64 character into a six bit pattern |
return retArray; |
inline Uint8 Base64::_Decode(char c) |
|
{ |
|
if (c >= 'A' && c <= 'Z') |
|
return c - 'A'; |
|
if (c >= 'a' && c <= 'z') |
|
return c - 'a' + 26; |
|
|
|
if (c >= '0' && c <= '9') |
|
return c - '0' + 52; |
|
|
|
if (c == '+') |
|
return 62; |
|
|
|
return 63; |
|
}; | }; |
| |
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |