ULONG TextType::canonical(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst) { if (tt->texttype_fn_canonical) return (*tt->texttype_fn_canonical)(tt, srcLen, src, dstLen, dst); if (getCharSet()->isMultiByte()) { fb_assert(tt->texttype_canonical_width == sizeof(ULONG)); Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16_str; ULONG utf16_len = getCharSet()->getConvToUnicode().convertLength(srcLen); // convert to UTF-16 utf16_len = getCharSet()->getConvToUnicode().convert(srcLen, src, utf16_len, utf16_str.getBuffer(utf16_len)); USHORT errCode; ULONG errPos; // convert UTF-16 to UTF-32 return UnicodeUtil::utf16ToUtf32(utf16_len, Firebird::Aligner<USHORT>(utf16_str.begin(), utf16_len), dstLen, Firebird::OutAligner<ULONG>(dst, dstLen), &errCode, &errPos) / sizeof(ULONG); } fb_assert( (tt->texttype_canonical_width == 0 && !tt->texttype_fn_canonical) || tt->texttype_canonical_width == getCharSet()->minBytesPerChar()); fb_assert(dstLen >= srcLen); memcpy(dst, src, srcLen); return srcLen / getCharSet()->minBytesPerChar(); }
/** * Creates a plain text (or html) email and * specifies the necessary MIME types if needed * due to attaching base64 files. * when this function is done, it will rewind * the file position and return an open file **/ static dstrbuf * createPlainEmail(dstrbuf *msg) { dstrbuf *border=NULL; dstrbuf *buf=DSB_NEW; CharSetType cs; if (Mopts.attach) { border = mimeMakeBoundary(); } else { border = DSB_NEW; } if (Mopts.encoding) { cs = getCharSet((u_char *)msg->str); } else { cs = IS_ASCII; } printHeaders(border->str, buf, cs); if (makeMessage(msg, buf, border->str, cs) < 0) { dsbDestroy(buf); buf=NULL; } dsbDestroy(border); return buf; }
ULONG TextType::str_to_lower(ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst) { if (tt->texttype_fn_str_to_lower) return (*tt->texttype_fn_str_to_lower)(tt, srcLen, src, dstLen, dst); return Firebird::IntlUtil::toLower(getCharSet(), srcLen, src, dstLen, dst, NULL); }
USHORT TextType::string_to_key(USHORT srcLen, const UCHAR* src, USHORT dstLen, UCHAR* dst, USHORT key_type) { if (tt->texttype_fn_string_to_key) return (*tt->texttype_fn_string_to_key)(tt, srcLen, src, dstLen, dst, key_type); const UCHAR* space = getCharSet()->getSpace(); BYTE spaceLength = getCharSet()->getSpaceLength(); Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16Str; UCHAR utf16Space[sizeof(ULONG)]; if (getCharSet()->isMultiByte()) { // convert src to UTF-16 const ULONG utf16Length = getCharSet()->getConvToUnicode().convertLength(srcLen); srcLen = getCharSet()->getConvToUnicode().convert(srcLen, src, utf16Length, utf16Str.getBuffer(utf16Length)); src = utf16Str.begin(); // convert charset space to UTF-16 spaceLength = getCharSet()->getConvToUnicode().convert(spaceLength, space, sizeof(utf16Space), utf16Space); fb_assert(spaceLength == 2); // space character can't be surrogate for default string_to_key space = utf16Space; } if (tt->texttype_pad_option) { const UCHAR* pad; for (pad = src + srcLen - spaceLength; pad >= src; pad -= spaceLength) { if (memcmp(pad, space, spaceLength) != 0) break; } srcLen = pad - src + spaceLength; } if (getCharSet()->isMultiByte()) { dstLen = UnicodeUtil::utf16ToKey(srcLen, Firebird::Aligner<USHORT>(src, srcLen), dstLen, dst); } else { if (dstLen >= srcLen) { memcpy(dst, src, srcLen); dstLen = srcLen; } else dstLen = INTL_BAD_KEY_LENGTH; } return dstLen; }
USHORT TextType::key_length(USHORT len) { if (tt->texttype_fn_key_length) return (*tt->texttype_fn_key_length)(tt, len); if (getCharSet()->isMultiByte()) return UnicodeUtil::utf16KeyLength(len); return len; }
/** * This function takes the current content that was copied * in to us and creates a final message with the email header * and the appended content. It will also attach any files * that were specified at the command line. **/ static void printHeaders(const char *border, dstrbuf *msg, CharSetType msg_cs) { char *subject=Mopts.subject; char *user_name = getConfValue("MY_NAME"); char *email_addr = getConfValue("MY_EMAIL"); char *sm_bin = getConfValue("SENDMAIL_BIN"); char *smtp_serv = getConfValue("SMTP_SERVER"); char *reply_to = getConfValue("REPLY_TO"); dstrbuf *dsb=NULL; if (subject) { if (Mopts.encoding) { CharSetType cs = getCharSet((u_char *)subject); if (cs == IS_UTF8) { dsb = encodeUtf8String((u_char *)subject, false); subject = dsb->str; } else if (cs == IS_PARTIAL_UTF8) { dsb = encodeUtf8String((u_char *)subject, true); subject = dsb->str; } } dsbPrintf(msg, "Subject: %s\r\n", subject); if (dsb) { dsbDestroy(dsb); } } printFromHeaders(user_name, email_addr, msg); printToHeaders(Mopts.to, Mopts.cc, msg); /** * We want to check here to see if we are sending mail by invoking sendmail * If so, We want to add the BCC line to the headers. Sendmail checks this * Line and makes sure it sends the mail to the BCC people, and then remove * the BCC addresses... Keep in mind that sending to an smtp servers takes * presidence over sending to sendmail incase both are mentioned. */ if (sm_bin && !smtp_serv) { printBccHeaders(Mopts.bcc, msg); } /* The rest of the standard headers */ printDateHeaders(msg); if (reply_to) { dsbPrintf(msg, "Reply-To: <%s>\r\n", reply_to); } printMimeHeaders(border, msg, msg_cs); dsbPrintf(msg, "X-Mailer: Cleancode.email v%s \r\n", EMAIL_VERSION); if (Mopts.priority) { dsbPrintf(msg, "X-Priority: 1\r\n"); } printExtraHeaders(Mopts.headers, msg); dsbPrintf(msg, "\r\n"); }
char* Param::getDisplayValue(CharInfo::CharSet display_cs) { if ( isInSingleByteForm() == FALSE && getCharSet() == CharInfo::UNICODE ) { if ( display_value == NULL ) { NAWchar* wvalue = (NAWchar*)value; Lng32 wlen = (Lng32)NAWstrlen(wvalue); display_value = new char[wlen+1]; UnicodeStringToLocale(display_cs, wvalue, wlen, display_value, wlen+1, TRUE, // add null at end TRUE // non-convertable char to ? ); } return display_value; } else return getValue(); }
short Param::convertValue(SqlciEnv * sqlci_env, short targetType, Lng32 &targetLen, Lng32 targetPrecision, Lng32 targetScale, Lng32 vcIndLen, ComDiagsArea* diags) { // get rid of the old converted value if (converted_value) { delete [] converted_value; converted_value = 0; }; short sourceType; Lng32 sourceLen; // set up the source and its length based on the how the value is passed-in. if ( isInSingleByteForm() == FALSE ) { sourceLen = (Lng32)(NAWstrlen((NAWchar*)value) * BYTES_PER_NAWCHAR); switch (getCharSet()) { case CharInfo::UNICODE: sourceType = REC_NCHAR_F_UNICODE; break; case CharInfo::KANJI_MP: case CharInfo::KSC5601_MP: sourceType = REC_BYTE_F_ASCII; // KANJI/KSC passed in as NAWchar* break; default: return SQL_Error; // error case } } else { sourceLen = (Lng32)strlen(value); // for any source in single-byte format sourceType = REC_BYTE_F_ASCII; } char * pParamValue = value; if ( DFS2REC::isAnyCharacter(targetType) ) { if (termCS_ == CharInfo::UnknownCharSet) termCS_ = sqlci_env->getTerminalCharset(); if (cs == CharInfo::UnknownCharSet) { isQuotedStrWithoutCharSetPrefix_ = TRUE; cs = termCS_; } // If the target is CHARACTER and param is set as [_cs_prefix]'...', then // make sure the source is assignment compatible with the target. CharInfo::CharSet targetCharSet = (CharInfo::CharSet)targetScale; if ( targetCharSet == CharInfo::UNICODE ) { if (getUTF16StrLit() == (NAWchar*)NULL) { utf16StrLit_ = new NAWchar [ sourceLen * 2 + 1 ]; // plenty of room Lng32 utf16StrLenInNAWchars = LocaleStringToUnicode(cs/*sourceCS*/, /*sourceStr*/value, sourceLen, utf16StrLit_/*outputBuf*/, sourceLen+1/*outputBufSizeInNAWchars*/, TRUE /* in - NABoolean addNullAtEnd*/); if (sourceLen > 0 && utf16StrLenInNAWchars == 0) return SQL_Error; // ComASSERT(utf16StrLenInNAWchars == NAWstrlen(getUTF16StrLit())); // Resize the NAWchar buffer to save space NAWchar *pNAWcharBuf = new NAWchar [ utf16StrLenInNAWchars + 1 ]; NAWstrncpy (pNAWcharBuf, utf16StrLit_, utf16StrLenInNAWchars + 1); pNAWcharBuf[utf16StrLenInNAWchars] = NAWCHR('\0'); // play it safe delete [] utf16StrLit_; utf16StrLit_ = pNAWcharBuf; // do not deallocate pNAWcharBuf } sourceLen = (Lng32)(NAWstrlen(getUTF16StrLit()) * BYTES_PER_NAWCHAR); // check to see if the parameter utf16 string fits in the target if ( sourceLen > targetLen ) return SQL_Error; pParamValue = (char *)getUTF16StrLit(); sourceType = REC_NCHAR_F_UNICODE; } } else { // MP NCHAR (KANJI/KSC) can not be converted to non-character objects if ( CharInfo::is_NCHAR_MP(cs) ) return SQL_Error; } switch(targetType) { case REC_BIN16_SIGNED: case REC_BIN16_UNSIGNED: case REC_BPINT_UNSIGNED: case REC_BIN32_SIGNED: case REC_BIN32_UNSIGNED: case REC_BIN64_SIGNED: case REC_DECIMAL_UNSIGNED: case REC_DECIMAL_LSE: case REC_FLOAT32: case REC_FLOAT64: case REC_TDM_FLOAT32: case REC_TDM_FLOAT64: case REC_BYTE_F_ASCII: case REC_BYTE_V_ASCII: case REC_BYTE_V_ASCII_LONG: case REC_NCHAR_F_UNICODE: case REC_NCHAR_V_UNICODE: { char *VCLen = NULL; short VCLenSize = 0; // 5/27/98: added VARNCHAR cases if ((targetType == REC_BYTE_V_ASCII) || (targetType == REC_BYTE_V_ASCII_LONG) || (targetType == REC_NCHAR_V_UNICODE)) { // add bytes for variable length field VCLenSize = vcIndLen; //sizeof(short); VCLen = converted_value = new char[targetLen + VCLenSize]; } else converted_value = new char[targetLen]; #pragma nowarn(1506) // warning elimination ex_expr::exp_return_type ok; CharInfo::CharSet TCS = sqlci_env->getTerminalCharset(); CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset(); NAString* tempstr; if ( DFS2REC::isAnyCharacter(sourceType) && DFS2REC::isAnyCharacter(targetType) && !(getUTF16StrLit() != NULL && sourceType == REC_NCHAR_F_UNICODE && targetScale == CharInfo::UCS2) && /*source*/cs != targetScale/*i.e., targetCharSet*/ ) { charBuf cbuf((unsigned char*)pParamValue, sourceLen); NAWcharBuf* wcbuf = 0; Int32 errorcode = 0; wcbuf = csetToUnicode(cbuf, 0, wcbuf, cs/*sourceCharSet*/ , errorcode); if (errorcode != 0) return SQL_Error; tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), targetScale/*i.e., targetCharSet*/ ); if (tempstr == NULL) return SQL_Error; //Avoid NULL ptr reference if conversion error sourceType = targetType; // we just converted it to the target type sourceLen = tempstr->length(); pParamValue = (char *)tempstr->data(); if ( sourceLen > targetLen ) return SQL_Error; } ok = convDoIt(pParamValue, sourceLen, sourceType, 0, // source Precision targetScale, // new charset we converted to &converted_value[VCLenSize], targetLen, targetType, targetPrecision, targetScale, VCLen, VCLenSize, 0, &diags); if ( ok != ex_expr::EXPR_OK) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_DATETIME: { char *VCLen = NULL; short VCLenSize = 0; converted_value = new char[targetLen + 1]; #pragma nowarn(1506) // warning elimination ex_expr::exp_return_type ok = convDoIt(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, VCLen, VCLenSize, 0, &diags); if ( ok != ex_expr::EXPR_OK) { return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_INT_YEAR: case REC_INT_MONTH: case REC_INT_YEAR_MONTH: case REC_INT_DAY: case REC_INT_HOUR: case REC_INT_DAY_HOUR: case REC_INT_MINUTE: case REC_INT_HOUR_MINUTE: case REC_INT_DAY_MINUTE: case REC_INT_SECOND: case REC_INT_MINUTE_SECOND: case REC_INT_HOUR_SECOND: case REC_INT_DAY_SECOND: { // convert target back to string. converted_value = new char[targetLen]; Lng32 convFlags = CONV_ALLOW_SIGN_IN_INTERVAL; #pragma nowarn(1506) // warning elimination short ok = convDoItMxcs(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, convFlags); if ( ok != 0 ) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; case REC_NUM_BIG_UNSIGNED: case REC_NUM_BIG_SIGNED: { converted_value = new char[targetLen]; #pragma nowarn(1506) // warning elimination short ok = convDoItMxcs(value, sourceLen, sourceType, 0, // source Precision 0, // source Scale converted_value, targetLen, targetType, targetPrecision, targetScale, 0); if ( ok != 0 ) { // No need to delete allocated memory before return because class member // converted_value still points to allocated memory that is deleted in // desctructor. return SQL_Error; // error case } #pragma warn(1506) // warning elimination }; break; default: break; }; return 0; }
static char * formatMessage(char ** addrs, const char * subject, const char * body) { char * msg; int size = 0; int line; char ** to; int isAllASCII; char hdr_buf[1024]; _DtXlateDb db = NULL; char plat[_DtPLATFORM_MAX_LEN]; int execver; int compver; int body_len; char digest[16]; char mime_type[64]; char tmpbuf[20]; char *ret_locale = NULL; char *ret_lang = NULL; char *ret_codeset = NULL; char default_charset[64]; char *NewBuf = NULL; unsigned long _len = 0; Encoding enc; /* Figure out how big we need the buffer to be. */ for (to = addrs; *to; to++) { size += strlen(*to); size += 2; /* Leave room for the , */ } size += strlen(subject); size += strlen(body); /* We will need space for the header names, a blank line, and other general formatting things. We could be exact, but 1024 is more than enough and give us some spare. */ size += 1024; msg = (char *)malloc(size); strcpy(msg, "To: "); line = 4; for (to = addrs; *to; to++) { strcat(msg, *to); if (*(to + 1) != NULL) { strcat(msg, ", "); line += strlen(*to); if (line > 72) { strcat(msg, "\n "); line = 0; } } } strcat(msg, "\nSubject: "); /* Encode the body of the message */ /* 1) Open Lcx data bases */ if ((_DtLcxOpenAllDbs(&db) == 0) && (_DtXlateGetXlateEnv(db,plat,&execver,&compver) != 0)) { _DtLcxCloseDb(&db); strcat(msg, subject); if (msg[strlen(msg) - 1] == '\n') { msg[strlen(msg) - 1] = 0; } strcat(msg, "\nMime-Version: 1.0\n"); strcat(msg, "Content-Type: text/plain;charset=us-ascii\n\n"); strcat(msg, body); } else { body_len = strlen(body); hdr_buf[0]='\0'; strcpy(mime_type,"text/plain"); rfc1522cpy(hdr_buf,subject); strcat(hdr_buf,"Mime-Version: 1.0\n"); isAllASCII= CvtStr((char *)NULL,(void *)body,(unsigned long)body_len,(void**)&NewBuf, &_len, CURRENT_TO_INTERNET); enc = getEncodingType(body,body_len,FALSE); /* * Here is an ugly adjustment again. If mime_type is text/plain and if * ret_codeset is ISO-2022-JP/KR/TW/CN, we have to always use * enc = MIME_7BIT * This means if the user inputs UDC/VDC into the e-mail body, * fold7 may convert it to the string with MSB-on character and * dtmail passes it to sendmail as if I had all 7bit chars. */ getCharSet(default_charset); DtXlateOpToStdLocale(DtLCX_OPER_MIME, default_charset, &ret_locale, &ret_lang, &ret_codeset); if ( !strncasecmp( mime_type, "text/plain", 10 ) && ( !strncasecmp( ret_codeset, "ISO-2022-JP", 11 ) || !strncasecmp( ret_codeset, "ISO-2022-KR", 11 ) || !strncasecmp( ret_codeset, "ISO-2022-TW", 11 ) || !strncasecmp( ret_codeset, "ISO-2022-CN", 11 ) ) ) enc = MIME_7BIT; memset(digest,0,sizeof(digest)); md5PlainText(body,body_len,digest); writeContentHeaders(hdr_buf,mime_type,enc,(char *)digest,isAllASCII); strcat(hdr_buf,"\n"); strcat(hdr_buf,"Content-Length: "); if (( NewBuf != NULL) && ( _len != 0)) { sprintf(tmpbuf,"%ld",_len); strcat(hdr_buf,tmpbuf); strcat(hdr_buf,"\n"); strcat(msg,hdr_buf); strncat(msg,NewBuf,_len); strcat(hdr_buf,"\n"); } else { sprintf(tmpbuf,"%d",body_len); strcat(hdr_buf,tmpbuf); strcat(hdr_buf,"\n"); strcat(msg,hdr_buf); strcat(msg,body); } } return(msg); }
SSHORT TextType::compare(ULONG len1, const UCHAR* str1, ULONG len2, const UCHAR* str2) { INTL_BOOL error = false; if (tt->texttype_fn_compare) return (*tt->texttype_fn_compare)(tt, len1, str1, len2, str2, &error); const UCHAR* space = getCharSet()->getSpace(); BYTE spaceLength = getCharSet()->getSpaceLength(); Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16Str1; Firebird::HalfStaticArray<UCHAR, BUFFER_SMALL> utf16Str2; UCHAR utf16Space[sizeof(ULONG)]; if (getCharSet()->isMultiByte()) { // convert str1 to UTF-16 ULONG utf16Length = getCharSet()->getConvToUnicode().convertLength(len1); len1 = getCharSet()->getConvToUnicode().convert(len1, str1, utf16Length, utf16Str1.getBuffer(utf16Length)); str1 = utf16Str1.begin(); // convert str2 to UTF-16 utf16Length = getCharSet()->getConvToUnicode().convertLength(len2); len2 = getCharSet()->getConvToUnicode().convert(len2, str2, utf16Length, utf16Str2.getBuffer(utf16Length)); str2 = utf16Str2.begin(); // convert charset space to UTF-16 spaceLength = getCharSet()->getConvToUnicode().convert(spaceLength, space, sizeof(utf16Space), utf16Space); fb_assert(spaceLength == 2); // space character can't be surrogate for default compare space = utf16Space; } if (tt->texttype_pad_option) { const UCHAR* pad; for (pad = str1 + len1 - spaceLength; pad >= str1; pad -= spaceLength) { if (memcmp(pad, space, spaceLength) != 0) break; } len1 = pad - str1 + spaceLength; for (pad = str2 + len2 - spaceLength; pad >= str2; pad -= spaceLength) { if (memcmp(pad, space, spaceLength) != 0) break; } len2 = pad - str2 + spaceLength; } if (getCharSet()->isMultiByte()) { INTL_BOOL error_flag; return UnicodeUtil::utf16Compare(len1, Firebird::Aligner<USHORT>(str1, len1), len2, Firebird::Aligner<USHORT>(str2, len2), &error_flag); } SSHORT cmp = memcmp(str1, str2, MIN(len1, len2)); if (cmp == 0) cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0)); return cmp; }
TextType::TextType(TTYPE_ID _type, texttype *_tt, CharSet* _cs) : tt(_tt), cs(_cs), type(_type) { canonical(cs->getSqlMatchAnyLength(), cs->getSqlMatchAny(), sizeof(ULONG), reinterpret_cast<UCHAR*>(&canonicalChars[CHAR_SQL_MATCH_ANY])); canonical(cs->getSqlMatchOneLength(), cs->getSqlMatchOne(), sizeof(ULONG), reinterpret_cast<UCHAR*>(&canonicalChars[CHAR_SQL_MATCH_ONE])); struct Conversion { USHORT code; int ch; }; const Conversion conversions[] = { {'*', CHAR_ASTERISK}, {'@', CHAR_AT}, {'^', CHAR_CIRCUMFLEX}, {':', CHAR_COLON}, {',', CHAR_COMMA}, {'=', CHAR_EQUAL}, {'-', CHAR_MINUS}, {'%', CHAR_PERCENT}, {'+', CHAR_PLUS}, {'?', CHAR_QUESTION_MARK}, {' ', CHAR_SPACE}, {'~', CHAR_TILDE}, {'_', CHAR_UNDERLINE}, {'|', CHAR_VERTICAL_BAR}, {'{', CHAR_OPEN_BRACE}, {'}', CHAR_CLOSE_BRACE}, {'[', CHAR_OPEN_BRACKET}, {']', CHAR_CLOSE_BRACKET}, {'(', CHAR_OPEN_PAREN}, {')', CHAR_CLOSE_PAREN}, {'s', CHAR_LOWER_S}, {'S', CHAR_UPPER_S} }; for (int i = 0; i < FB_NELEM(conversions); i++) { UCHAR temp[sizeof(ULONG)]; ULONG length = getCharSet()->getConvFromUnicode().convert( sizeof(USHORT), &conversions[i].code, sizeof(temp), temp); canonical(length, temp, sizeof(ULONG), reinterpret_cast<UCHAR*>(&canonicalChars[conversions[i].ch])); } struct Conversion2 { const char* str; UCHAR* buffer; }; const Conversion2 conversions2[] = { {"0123456789", reinterpret_cast<UCHAR*>(canonicalNumbers)}, {"abcdefghijklmnopqrstuvwxyz", reinterpret_cast<UCHAR*>(canonicalLowerLetters)}, {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", reinterpret_cast<UCHAR*>(canonicalUpperLetters)}, {" \t\v\r\n\f", reinterpret_cast<UCHAR*>(canonicalWhiteSpaces)} }; for (int i = 0; i < FB_NELEM(conversions2); i++) { UCHAR temp[sizeof(ULONG)]; for (const char* p = conversions2[i].str; *p; ++p) { USHORT code = static_cast<USHORT>(*p); ULONG length = getCharSet()->getConvFromUnicode().convert(sizeof(code), &code, sizeof(temp), temp); const size_t pos = (p - conversions2[i].str) * getCanonicalWidth(); canonical(length, temp, sizeof(ULONG), &conversions2[i].buffer[pos]); } } }