mirror of
https://github.com/chatmail/core.git
synced 2026-04-20 23:16:30 +03:00
commit6bc5d1b90eAuthor: holger krekel <holger@merlinux.eu> Date: Sun Jul 21 22:56:37 2019 +0200 fix fmt commit197d94ad9dMerge:7ce337c686678cAuthor: holger krekel <holger@merlinux.eu> Date: Sun Jul 21 22:51:16 2019 +0200 Merge remote-tracking branch 'origin/master' into eventlogging commit7ce337c6d0Author: holger krekel <holger@merlinux.eu> Date: Sun Jul 21 22:44:27 2019 +0200 left-over error logging commit10148d2e43Author: holger krekel <holger@merlinux.eu> Date: Sun Jul 21 22:03:17 2019 +0200 ignore non-utf8 parts of header fields (add comment why it shouldn't happen) don't throw error if no sql rows are returned commit69dc237ee3Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Sun Jul 21 12:56:04 2019 +0200 fix(receive_imf): remove recursive sql call commitdf5464ea80Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Sat Jul 20 17:05:24 2019 +0200 fix: blocked is an optional value commite4bf9956a5Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Sat Jul 20 16:50:56 2019 +0200 fix(msg): handle optional in_reply_to commitd353d9d9d8Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Sat Jul 20 16:17:25 2019 +0200 fix(chat): remove recursive sql usage commit1ad45ed4d6Author: holger krekel <holger@merlinux.eu> Date: Sat Jul 20 15:14:11 2019 +0200 fix rust fmt commit496e980a17Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Sat Jul 20 14:34:20 2019 +0200 use forked rusqlite commitfa09e46ed9Author: holger krekel <holger@merlinux.eu> Date: Sat Jul 20 12:37:51 2019 +0200 another pace where we might (and in my case did) get invalid utf8 commitd6de420b9aAuthor: holger krekel <holger@merlinux.eu> Date: Sat Jul 20 12:30:48 2019 +0200 fix some string issues, introduce to_string_lossy such that to_string() continues to panic on non-utf8 commit38eb708db8Author: holger krekel <holger@merlinux.eu> Date: Sat Jul 20 01:17:53 2019 +0200 for now make to_string() less strict as we often don't want to crash the whole app just because some non-proper utf8 came in (through a message we can't neccesarily congtrol) commit7a59da5f8fAuthor: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 22:48:39 2019 +0200 fix linting commitf13a1d4a2fAuthor: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 22:46:58 2019 +0200 fix some test flakyness commit7b3a450918Author: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 22:35:07 2019 +0200 - fix saved_mime test which broke to improper conversion of imf_raw_not_terminated - some cargo.toml updates no clue where they come from - log Message-ID for received messages commit169923b102Author: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 12:31:22 2019 +0200 formatting commit42688a0622Author: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 12:24:56 2019 +0200 remove some print statements commit35f3c0edd1Merge:e7a2362f58b1d6Author: holger krekel <holger@merlinux.eu> Date: Fri Jul 19 10:25:21 2019 +0200 Merge branch 'master' into eventlogging commite7a236264aAuthor: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 23:20:20 2019 +0200 print invalid strings commitaaa5b820d9Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 23:12:35 2019 +0200 cleanup commite7f0745010Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 23:03:57 2019 +0200 reduce direc usage of CString commitc68e7ae14eAuthor: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 22:47:47 2019 +0200 audit use of to_cstring and fix ub commit618087e5a7Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 21:38:52 2019 +0200 fix(imap): body ptr lifetime commit245abb8384Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 19:44:10 2019 +0200 remove debug commita3e1042001Author: dignifiedquire <dignifiedquire@users.noreply.github.com> Date: Thu Jul 18 18:30:54 2019 +0200 fix some things, add more debugging statements commit7b7ce9348fAuthor: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 15:11:57 2019 +0200 fix python lint issues commit7a4808ba0dAuthor: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 14:35:54 2019 +0200 cargofmt commit8f240f7153Author: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 14:03:57 2019 +0200 (dig,hpk) pull out job collection from sql query/lock logic commit7d0b5d8abbAuthor: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 12:52:02 2019 +0200 remove print statements and fix a crash commitee317cb1b5Author: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 11:38:10 2019 +0200 fix some merge issues commit7b736fe635Author: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 11:16:38 2019 +0200 (dig,hpk) add test and fix for wrong dbs commitc7db15352aMerge:0b371670c5015dAuthor: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 09:59:44 2019 +0200 Merge branch 'master' into eventlogging commit0b37167be8Author: holger krekel <holger@merlinux.eu> Date: Thu Jul 18 00:06:05 2019 +0200 address @dignifiedquire comments commit5cac4b5076Author: holger krekel <holger@merlinux.eu> Date: Wed Jul 17 12:47:22 2019 +0200 remove spurious print commit475a41beb3Author: holger krekel <holger@merlinux.eu> Date: Wed Jul 17 12:31:12 2019 +0200 address @dignifiedquire rustyness comment and fix changelog commitad4be80b4eAuthor: holger krekel <holger@merlinux.eu> Date: Wed Jul 17 10:25:25 2019 +0200 make smtp/imap connect() return bool instead of c-int commit8737c1d142Author: holger krekel <holger@merlinux.eu> Date: Wed Jul 17 09:26:33 2019 +0200 cleanup some parts, add comments commit964fe466ccAuthor: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 20:05:41 2019 +0200 wip-commit which passes all tests with proper finalization commit43936e7db7Author: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 16:17:42 2019 +0200 snapshot of my current debugging state commit0e80ce9c39Author: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 12:57:19 2019 +0200 more aggressively skip perform API when threads are closing commitc652bae68aAuthor: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 12:06:05 2019 +0200 intermediate wip commit commitbc904a495dAuthor: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 11:18:56 2019 +0200 add some logging, and a more precise teardown for online python tests commit8d99444c6aAuthor: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 00:22:12 2019 +0200 fix std commit9dab53e0afAuthor: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 00:20:54 2019 +0200 rustfmt commit360089ac74Author: holger krekel <holger@merlinux.eu> Date: Tue Jul 16 00:03:49 2019 +0200 remove some debugging commite892c5cf4dAuthor: holger krekel <holger@merlinux.eu> Date: Mon Jul 15 23:31:30 2019 +0200 fix test for events commit9ad4c9a6feAuthor: holger krekel <holger@merlinux.eu> Date: Mon Jul 15 22:51:57 2019 +0200 wip try test that we see INFO events from the core
962 lines
34 KiB
Rust
962 lines
34 KiB
Rust
use std::ffi::CStr;
|
|
|
|
use charset::Charset;
|
|
use mmime::mailmime_decode::*;
|
|
use mmime::mmapstring::*;
|
|
use mmime::other::*;
|
|
|
|
use crate::dc_tools::*;
|
|
use crate::types::*;
|
|
use crate::x::*;
|
|
|
|
#[inline]
|
|
pub fn isalnum(c: libc::c_int) -> libc::c_int {
|
|
if c < std::u8::MAX as libc::c_int {
|
|
(c as u8 as char).is_ascii_alphanumeric() as libc::c_int
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
pub unsafe fn dc_urlencode(to_encode: *const libc::c_char) -> *mut libc::c_char {
|
|
let mut pstr: *const libc::c_char = to_encode;
|
|
if to_encode.is_null() {
|
|
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
let buf: *mut libc::c_char =
|
|
malloc(strlen(to_encode).wrapping_mul(3).wrapping_add(1)) as *mut libc::c_char;
|
|
let mut pbuf: *mut libc::c_char = buf;
|
|
assert!(!buf.is_null());
|
|
|
|
while 0 != *pstr {
|
|
if 0 != isalnum(*pstr as libc::c_int)
|
|
|| *pstr as libc::c_int == '-' as i32
|
|
|| *pstr as libc::c_int == '_' as i32
|
|
|| *pstr as libc::c_int == '.' as i32
|
|
|| *pstr as libc::c_int == '~' as i32
|
|
{
|
|
let fresh0 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh0 = *pstr
|
|
} else if *pstr as libc::c_int == ' ' as i32 {
|
|
let fresh1 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh1 = '+' as i32 as libc::c_char
|
|
} else {
|
|
let fresh2 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh2 = '%' as i32 as libc::c_char;
|
|
let fresh3 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh3 = int_2_uppercase_hex((*pstr as libc::c_int >> 4i32) as libc::c_char);
|
|
let fresh4 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh4 = int_2_uppercase_hex((*pstr as libc::c_int & 15i32) as libc::c_char)
|
|
}
|
|
pstr = pstr.offset(1isize)
|
|
}
|
|
*pbuf = '\u{0}' as i32 as libc::c_char;
|
|
|
|
buf
|
|
}
|
|
|
|
/* ******************************************************************************
|
|
* URL encoding and decoding, RFC 3986
|
|
******************************************************************************/
|
|
unsafe fn int_2_uppercase_hex(code: libc::c_char) -> libc::c_char {
|
|
static mut hex: [libc::c_char; 17] = [
|
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 0,
|
|
];
|
|
|
|
hex[(code as libc::c_int & 15i32) as usize]
|
|
}
|
|
|
|
pub unsafe fn dc_urldecode(to_decode: *const libc::c_char) -> *mut libc::c_char {
|
|
let mut pstr: *const libc::c_char = to_decode;
|
|
if to_decode.is_null() {
|
|
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
let buf: *mut libc::c_char = malloc(strlen(to_decode).wrapping_add(1)) as *mut libc::c_char;
|
|
let mut pbuf: *mut libc::c_char = buf;
|
|
assert!(!buf.is_null());
|
|
|
|
while 0 != *pstr {
|
|
if *pstr as libc::c_int == '%' as i32 {
|
|
if 0 != *pstr.offset(1isize) as libc::c_int && 0 != *pstr.offset(2isize) as libc::c_int
|
|
{
|
|
let fresh5 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh5 = ((hex_2_int(*pstr.offset(1isize)) as libc::c_int) << 4i32
|
|
| hex_2_int(*pstr.offset(2isize)) as libc::c_int)
|
|
as libc::c_char;
|
|
pstr = pstr.offset(2isize)
|
|
}
|
|
} else if *pstr as libc::c_int == '+' as i32 {
|
|
let fresh6 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh6 = ' ' as i32 as libc::c_char
|
|
} else {
|
|
let fresh7 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh7 = *pstr
|
|
}
|
|
pstr = pstr.offset(1isize)
|
|
}
|
|
*pbuf = '\u{0}' as i32 as libc::c_char;
|
|
|
|
buf
|
|
}
|
|
|
|
fn hex_2_int(ch: libc::c_char) -> libc::c_char {
|
|
let ch = ch as u8 as char;
|
|
if !ch.is_ascii_hexdigit() {
|
|
return (ch.to_ascii_lowercase() as i32 - 'a' as i32 + 10) as libc::c_char;
|
|
}
|
|
|
|
match ch.to_digit(16) {
|
|
Some(res) => res as libc::c_char,
|
|
None => 0,
|
|
}
|
|
}
|
|
|
|
pub unsafe fn dc_encode_header_words(to_encode: *const libc::c_char) -> *mut libc::c_char {
|
|
let mut current_block: u64;
|
|
let mut ret_str: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut cur: *const libc::c_char = to_encode;
|
|
let mmapstr: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
|
if to_encode.is_null() || mmapstr.is_null() {
|
|
current_block = 8550051112593613029;
|
|
} else {
|
|
current_block = 4644295000439058019;
|
|
}
|
|
loop {
|
|
match current_block {
|
|
8550051112593613029 => {
|
|
if !mmapstr.is_null() {
|
|
mmap_string_free(mmapstr);
|
|
}
|
|
break;
|
|
}
|
|
_ => {
|
|
if *cur as libc::c_int != '\u{0}' as i32 {
|
|
let begin: *const libc::c_char;
|
|
let mut end: *const libc::c_char;
|
|
let mut do_quote: bool;
|
|
let mut quote_words: libc::c_int;
|
|
begin = cur;
|
|
end = begin;
|
|
quote_words = 0i32;
|
|
do_quote = true;
|
|
while *cur as libc::c_int != '\u{0}' as i32 {
|
|
get_word(cur, &mut cur, &mut do_quote);
|
|
if !do_quote {
|
|
break;
|
|
}
|
|
quote_words = 1i32;
|
|
end = cur;
|
|
if *cur as libc::c_int != '\u{0}' as i32 {
|
|
cur = cur.offset(1isize)
|
|
}
|
|
}
|
|
if 0 != quote_words {
|
|
if !quote_word(
|
|
b"utf-8\x00" as *const u8 as *const libc::c_char,
|
|
mmapstr,
|
|
begin,
|
|
end.wrapping_offset_from(begin) as size_t,
|
|
) {
|
|
current_block = 8550051112593613029;
|
|
continue;
|
|
}
|
|
if *end as libc::c_int == ' ' as i32 || *end as libc::c_int == '\t' as i32 {
|
|
if mmap_string_append_c(mmapstr, *end).is_null() {
|
|
current_block = 8550051112593613029;
|
|
continue;
|
|
}
|
|
end = end.offset(1isize)
|
|
}
|
|
if *end as libc::c_int != '\u{0}' as i32 {
|
|
if mmap_string_append_len(
|
|
mmapstr,
|
|
end,
|
|
cur.wrapping_offset_from(end) as size_t,
|
|
)
|
|
.is_null()
|
|
{
|
|
current_block = 8550051112593613029;
|
|
continue;
|
|
}
|
|
}
|
|
} else if mmap_string_append_len(
|
|
mmapstr,
|
|
begin,
|
|
cur.wrapping_offset_from(begin) as size_t,
|
|
)
|
|
.is_null()
|
|
{
|
|
current_block = 8550051112593613029;
|
|
continue;
|
|
}
|
|
if !(*cur as libc::c_int == ' ' as i32 || *cur as libc::c_int == '\t' as i32) {
|
|
current_block = 4644295000439058019;
|
|
continue;
|
|
}
|
|
if mmap_string_append_c(mmapstr, *cur).is_null() {
|
|
current_block = 8550051112593613029;
|
|
continue;
|
|
}
|
|
cur = cur.offset(1isize);
|
|
current_block = 4644295000439058019;
|
|
} else {
|
|
ret_str = strdup((*mmapstr).str_0);
|
|
current_block = 8550051112593613029;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ret_str
|
|
}
|
|
|
|
unsafe fn quote_word(
|
|
display_charset: *const libc::c_char,
|
|
mmapstr: *mut MMAPString,
|
|
word: *const libc::c_char,
|
|
size: size_t,
|
|
) -> bool {
|
|
let mut cur: *const libc::c_char;
|
|
let mut i: size_t = 0i32 as size_t;
|
|
let mut hex: [libc::c_char; 4] = [0; 4];
|
|
// let mut col: libc::c_int = 0i32;
|
|
if mmap_string_append(mmapstr, b"=?\x00" as *const u8 as *const libc::c_char).is_null() {
|
|
return false;
|
|
}
|
|
if mmap_string_append(mmapstr, display_charset).is_null() {
|
|
return false;
|
|
}
|
|
if mmap_string_append(mmapstr, b"?Q?\x00" as *const u8 as *const libc::c_char).is_null() {
|
|
return false;
|
|
}
|
|
// col = (*mmapstr).len as libc::c_int;
|
|
cur = word;
|
|
while i < size {
|
|
let mut do_quote_char = false;
|
|
match *cur as u8 as char {
|
|
',' | ':' | '!' | '"' | '#' | '$' | '@' | '[' | '\\' | ']' | '^' | '`' | '{' | '|'
|
|
| '}' | '~' | '=' | '?' | '_' => do_quote_char = true,
|
|
_ => {
|
|
if *cur as u8 >= 128 {
|
|
do_quote_char = true;
|
|
}
|
|
}
|
|
}
|
|
if do_quote_char {
|
|
print_hex(hex.as_mut_ptr(), cur);
|
|
if mmap_string_append(mmapstr, hex.as_mut_ptr()).is_null() {
|
|
return false;
|
|
}
|
|
// col += 3i32
|
|
} else {
|
|
if *cur as libc::c_int == ' ' as i32 {
|
|
if mmap_string_append_c(mmapstr, '_' as i32 as libc::c_char).is_null() {
|
|
return false;
|
|
}
|
|
} else if mmap_string_append_c(mmapstr, *cur).is_null() {
|
|
return false;
|
|
}
|
|
// col += 3i32
|
|
}
|
|
cur = cur.offset(1isize);
|
|
i = i.wrapping_add(1)
|
|
}
|
|
if mmap_string_append(mmapstr, b"?=\x00" as *const u8 as *const libc::c_char).is_null() {
|
|
return false;
|
|
}
|
|
|
|
true
|
|
}
|
|
|
|
unsafe fn get_word(
|
|
begin: *const libc::c_char,
|
|
pend: *mut *const libc::c_char,
|
|
pto_be_quoted: *mut bool,
|
|
) {
|
|
let mut cur: *const libc::c_char = begin;
|
|
while *cur as libc::c_int != ' ' as i32
|
|
&& *cur as libc::c_int != '\t' as i32
|
|
&& *cur as libc::c_int != '\u{0}' as i32
|
|
{
|
|
cur = cur.offset(1isize)
|
|
}
|
|
*pto_be_quoted = to_be_quoted(begin, cur.wrapping_offset_from(begin) as size_t);
|
|
*pend = cur;
|
|
}
|
|
|
|
/* ******************************************************************************
|
|
* Encode/decode header words, RFC 2047
|
|
******************************************************************************/
|
|
|
|
/* see comment below */
|
|
unsafe fn to_be_quoted(word: *const libc::c_char, size: size_t) -> bool {
|
|
let mut cur: *const libc::c_char = word;
|
|
let mut i: size_t = 0i32 as size_t;
|
|
while i < size {
|
|
match *cur as libc::c_int {
|
|
44 | 58 | 33 | 34 | 35 | 36 | 64 | 91 | 92 | 93 | 94 | 96 | 123 | 124 | 125 | 126
|
|
| 61 | 63 | 95 => return true,
|
|
_ => {
|
|
if *cur as libc::c_uchar as libc::c_int >= 128i32 {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
cur = cur.offset(1isize);
|
|
i = i.wrapping_add(1)
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub unsafe fn dc_decode_header_words(in_0: *const libc::c_char) -> *mut libc::c_char {
|
|
if in_0.is_null() {
|
|
return 0 as *mut libc::c_char;
|
|
}
|
|
let mut out: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut cur_token: size_t = 0i32 as size_t;
|
|
let r: libc::c_int = mailmime_encoded_phrase_parse(
|
|
b"iso-8859-1\x00" as *const u8 as *const libc::c_char,
|
|
in_0,
|
|
strlen(in_0),
|
|
&mut cur_token,
|
|
b"utf-8\x00" as *const u8 as *const libc::c_char,
|
|
&mut out,
|
|
);
|
|
if r != MAILIMF_NO_ERROR as libc::c_int || out.is_null() {
|
|
out = dc_strdup(in_0)
|
|
}
|
|
|
|
out
|
|
}
|
|
|
|
pub unsafe fn dc_encode_modified_utf7(
|
|
mut to_encode: *const libc::c_char,
|
|
change_spaces: libc::c_int,
|
|
) -> *mut libc::c_char {
|
|
let mut utf8pos: libc::c_uint;
|
|
let mut utf8total: libc::c_uint;
|
|
let mut c: libc::c_uint;
|
|
let mut utf7mode: libc::c_uint;
|
|
let mut bitstogo: libc::c_uint;
|
|
let mut utf16flag: libc::c_uint;
|
|
let mut ucs4: libc::c_ulong = 0;
|
|
let mut bitbuf: libc::c_ulong = 0;
|
|
let mut dst: *mut libc::c_char;
|
|
let res: *mut libc::c_char;
|
|
if to_encode.is_null() {
|
|
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
res = malloc(2usize.wrapping_mul(strlen(to_encode)).wrapping_add(1)) as *mut libc::c_char;
|
|
dst = res;
|
|
assert!(!dst.is_null());
|
|
|
|
utf7mode = 0i32 as libc::c_uint;
|
|
utf8total = 0i32 as libc::c_uint;
|
|
bitstogo = 0i32 as libc::c_uint;
|
|
utf8pos = 0i32 as libc::c_uint;
|
|
loop {
|
|
c = *to_encode as libc::c_uchar as libc::c_uint;
|
|
if !(c != '\u{0}' as i32 as libc::c_uint) {
|
|
break;
|
|
}
|
|
to_encode = to_encode.offset(1isize);
|
|
// normal character?
|
|
if c >= ' ' as i32 as libc::c_uint
|
|
&& c <= '~' as i32 as libc::c_uint
|
|
&& (c != '_' as i32 as libc::c_uint || 0 == change_spaces)
|
|
{
|
|
if 0 != utf7mode {
|
|
if 0 != bitstogo {
|
|
let fresh8 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh8 = base64chars
|
|
[(bitbuf << (6i32 as libc::c_uint).wrapping_sub(bitstogo) & 0x3f) as usize]
|
|
}
|
|
let fresh9 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh9 = '-' as i32 as libc::c_char;
|
|
utf7mode = 0i32 as libc::c_uint;
|
|
utf8pos = 0i32 as libc::c_uint;
|
|
bitstogo = 0i32 as libc::c_uint;
|
|
utf8total = 0i32 as libc::c_uint
|
|
}
|
|
if 0 != change_spaces && c == ' ' as i32 as libc::c_uint {
|
|
let fresh10 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh10 = '_' as i32 as libc::c_char
|
|
} else {
|
|
let fresh11 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh11 = c as libc::c_char
|
|
}
|
|
if c == '&' as i32 as libc::c_uint {
|
|
let fresh12 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh12 = '-' as i32 as libc::c_char
|
|
}
|
|
} else {
|
|
if 0 == utf7mode {
|
|
let fresh13 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh13 = '&' as i32 as libc::c_char;
|
|
utf7mode = 1i32 as libc::c_uint
|
|
}
|
|
// encode ascii characters as themselves
|
|
if c < 0x80i32 as libc::c_uint {
|
|
ucs4 = c as libc::c_ulong
|
|
} else if 0 != utf8total {
|
|
ucs4 = ucs4 << 6i32 | c as libc::c_ulong & 0x3f;
|
|
utf8pos = utf8pos.wrapping_add(1);
|
|
if utf8pos < utf8total {
|
|
continue;
|
|
}
|
|
} else {
|
|
utf8pos = 1i32 as libc::c_uint;
|
|
if c < 0xe0i32 as libc::c_uint {
|
|
utf8total = 2i32 as libc::c_uint;
|
|
ucs4 = (c & 0x1fi32 as libc::c_uint) as libc::c_ulong
|
|
} else if c < 0xf0i32 as libc::c_uint {
|
|
utf8total = 3i32 as libc::c_uint;
|
|
ucs4 = (c & 0xfi32 as libc::c_uint) as libc::c_ulong
|
|
} else {
|
|
utf8total = 4i32 as libc::c_uint;
|
|
ucs4 = (c & 0x3i32 as libc::c_uint) as libc::c_ulong
|
|
}
|
|
continue;
|
|
}
|
|
utf8total = 0i32 as libc::c_uint;
|
|
loop {
|
|
if ucs4 >= 0x10000 {
|
|
ucs4 = ucs4.wrapping_sub(0x10000);
|
|
bitbuf = bitbuf << 16 | (ucs4 >> 10).wrapping_add(0xd800);
|
|
ucs4 = (ucs4 & 0x3ff).wrapping_add(0xdc00);
|
|
utf16flag = 1i32 as libc::c_uint
|
|
} else {
|
|
bitbuf = bitbuf << 16 | ucs4;
|
|
utf16flag = 0i32 as libc::c_uint
|
|
}
|
|
bitstogo = bitstogo.wrapping_add(16i32 as libc::c_uint);
|
|
while bitstogo >= 6i32 as libc::c_uint {
|
|
bitstogo = bitstogo.wrapping_sub(6i32 as libc::c_uint);
|
|
let fresh14 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh14 = base64chars[(if 0 != bitstogo {
|
|
bitbuf >> bitstogo
|
|
} else {
|
|
bitbuf
|
|
} & 0x3f) as usize]
|
|
}
|
|
if !(0 != utf16flag) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if 0 != utf7mode {
|
|
if 0 != bitstogo {
|
|
let fresh15 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh15 = base64chars
|
|
[(bitbuf << (6i32 as libc::c_uint).wrapping_sub(bitstogo) & 0x3f) as usize]
|
|
}
|
|
let fresh16 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh16 = '-' as i32 as libc::c_char
|
|
}
|
|
*dst = '\u{0}' as i32 as libc::c_char;
|
|
|
|
res
|
|
}
|
|
|
|
/* ******************************************************************************
|
|
* Encode/decode modified UTF-7 as needed for IMAP, see RFC 2192
|
|
******************************************************************************/
|
|
|
|
// UTF7 modified base64 alphabet
|
|
static mut base64chars: [libc::c_char; 65] = [
|
|
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
|
|
89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
|
|
115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 44, 0,
|
|
];
|
|
|
|
pub unsafe fn dc_decode_modified_utf7(
|
|
to_decode: *const libc::c_char,
|
|
change_spaces: libc::c_int,
|
|
) -> *mut libc::c_char {
|
|
let mut c: libc::c_uint;
|
|
let mut i: libc::c_uint;
|
|
let mut bitcount: libc::c_uint;
|
|
let mut ucs4: libc::c_ulong;
|
|
let mut utf16: libc::c_ulong;
|
|
let mut bitbuf: libc::c_ulong;
|
|
let mut base64: [libc::c_uchar; 256] = [0; 256];
|
|
let mut src: *const libc::c_char;
|
|
let mut dst: *mut libc::c_char;
|
|
let res: *mut libc::c_char;
|
|
if to_decode.is_null() {
|
|
return dc_strdup(b"\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
res = malloc(4usize.wrapping_mul(strlen(to_decode)).wrapping_add(1)) as *mut libc::c_char;
|
|
dst = res;
|
|
src = to_decode;
|
|
assert!(!dst.is_null());
|
|
|
|
libc::memset(
|
|
base64.as_mut_ptr() as *mut libc::c_void,
|
|
64,
|
|
::std::mem::size_of::<[libc::c_uchar; 256]>(),
|
|
);
|
|
i = 0i32 as libc::c_uint;
|
|
while (i as libc::c_ulong) < ::std::mem::size_of::<[libc::c_char; 65]>() as libc::c_ulong {
|
|
base64[base64chars[i as usize] as libc::c_uint as usize] = i as libc::c_uchar;
|
|
i = i.wrapping_add(1)
|
|
}
|
|
while *src as libc::c_int != '\u{0}' as i32 {
|
|
let fresh17 = src;
|
|
src = src.offset(1);
|
|
c = *fresh17 as libc::c_uint;
|
|
if c != '&' as i32 as libc::c_uint || *src as libc::c_int == '-' as i32 {
|
|
if 0 != change_spaces && c == '_' as i32 as libc::c_uint {
|
|
let fresh18 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh18 = ' ' as i32 as libc::c_char
|
|
} else {
|
|
let fresh19 = dst;
|
|
dst = dst.offset(1);
|
|
*fresh19 = c as libc::c_char
|
|
}
|
|
if c == '&' as i32 as libc::c_uint {
|
|
src = src.offset(1isize)
|
|
}
|
|
} else {
|
|
bitbuf = 0;
|
|
bitcount = 0i32 as libc::c_uint;
|
|
ucs4 = 0;
|
|
loop {
|
|
c = base64[*src as libc::c_uchar as usize] as libc::c_uint;
|
|
if !(c != 64i32 as libc::c_uint) {
|
|
break;
|
|
}
|
|
src = src.offset(1isize);
|
|
bitbuf = bitbuf << 6i32 | c as libc::c_ulong;
|
|
bitcount = bitcount.wrapping_add(6i32 as libc::c_uint);
|
|
// enough bits for a UTF-16 character?
|
|
if !(bitcount >= 16i32 as libc::c_uint) {
|
|
continue;
|
|
}
|
|
bitcount = bitcount.wrapping_sub(16i32 as libc::c_uint);
|
|
utf16 = if 0 != bitcount {
|
|
bitbuf >> bitcount
|
|
} else {
|
|
bitbuf
|
|
} & 0xffff;
|
|
|
|
// convert UTF16 to UCS4
|
|
if utf16 >= 0xd800 && utf16 <= 0xdbff {
|
|
ucs4 = utf16.wrapping_sub(0xd800) << 10i32
|
|
} else {
|
|
if utf16 >= 0xdc00 && utf16 <= 0xdfff {
|
|
ucs4 = ucs4.wrapping_add(utf16.wrapping_sub(0xdc00).wrapping_add(0x10000))
|
|
} else {
|
|
ucs4 = utf16
|
|
}
|
|
if ucs4 <= 0x7f {
|
|
*dst.offset(0isize) = ucs4 as libc::c_char;
|
|
dst = dst.offset(1isize)
|
|
} else if ucs4 <= 0x7ff {
|
|
*dst.offset(0isize) = (0xc0 | ucs4 >> 6i32) as libc::c_char;
|
|
*dst.offset(1isize) = (0x80 | ucs4 & 0x3f) as libc::c_char;
|
|
dst = dst.offset(2isize)
|
|
} else if ucs4 <= 0xffff {
|
|
*dst.offset(0isize) = (0xe0 | ucs4 >> 12i32) as libc::c_char;
|
|
*dst.offset(1isize) = (0x80 | ucs4 >> 6i32 & 0x3f) as libc::c_char;
|
|
*dst.offset(2isize) = (0x80 | ucs4 & 0x3f) as libc::c_char;
|
|
dst = dst.offset(3isize)
|
|
} else {
|
|
*dst.offset(0isize) = (0xf0 | ucs4 >> 18i32) as libc::c_char;
|
|
*dst.offset(1isize) = (0x80 | ucs4 >> 12i32 & 0x3f) as libc::c_char;
|
|
*dst.offset(2isize) = (0x80 | ucs4 >> 6i32 & 0x3f) as libc::c_char;
|
|
*dst.offset(3isize) = (0x80 | ucs4 & 0x3f) as libc::c_char;
|
|
dst = dst.offset(4isize)
|
|
}
|
|
}
|
|
}
|
|
if *src as libc::c_int == '-' as i32 {
|
|
src = src.offset(1isize)
|
|
}
|
|
}
|
|
}
|
|
*dst = '\u{0}' as i32 as libc::c_char;
|
|
|
|
res
|
|
}
|
|
|
|
pub unsafe fn dc_needs_ext_header(mut to_check: *const libc::c_char) -> bool {
|
|
if !to_check.is_null() {
|
|
while 0 != *to_check {
|
|
if 0 == isalnum(*to_check as libc::c_int)
|
|
&& *to_check as libc::c_int != '-' as i32
|
|
&& *to_check as libc::c_int != '_' as i32
|
|
&& *to_check as libc::c_int != '.' as i32
|
|
&& *to_check as libc::c_int != '~' as i32
|
|
{
|
|
return true;
|
|
}
|
|
to_check = to_check.offset(1isize)
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub unsafe fn dc_encode_ext_header(to_encode: *const libc::c_char) -> *mut libc::c_char {
|
|
let mut pstr: *const libc::c_char = to_encode;
|
|
if to_encode.is_null() {
|
|
return dc_strdup(b"utf-8\'\'\x00" as *const u8 as *const libc::c_char);
|
|
}
|
|
let buf: *mut libc::c_char = malloc(
|
|
strlen(b"utf-8\'\'\x00" as *const u8 as *const libc::c_char)
|
|
.wrapping_add(strlen(to_encode).wrapping_mul(3))
|
|
.wrapping_add(1),
|
|
) as *mut libc::c_char;
|
|
assert!(!buf.is_null());
|
|
|
|
let mut pbuf: *mut libc::c_char = buf;
|
|
strcpy(pbuf, b"utf-8\'\'\x00" as *const u8 as *const libc::c_char);
|
|
pbuf = pbuf.offset(strlen(pbuf) as isize);
|
|
while 0 != *pstr {
|
|
if 0 != isalnum(*pstr as libc::c_int)
|
|
|| *pstr as libc::c_int == '-' as i32
|
|
|| *pstr as libc::c_int == '_' as i32
|
|
|| *pstr as libc::c_int == '.' as i32
|
|
|| *pstr as libc::c_int == '~' as i32
|
|
{
|
|
let fresh20 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh20 = *pstr
|
|
} else {
|
|
let fresh21 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh21 = '%' as i32 as libc::c_char;
|
|
let fresh22 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh22 = int_2_uppercase_hex((*pstr as libc::c_int >> 4i32) as libc::c_char);
|
|
let fresh23 = pbuf;
|
|
pbuf = pbuf.offset(1);
|
|
*fresh23 = int_2_uppercase_hex((*pstr as libc::c_int & 15i32) as libc::c_char)
|
|
}
|
|
pstr = pstr.offset(1isize)
|
|
}
|
|
*pbuf = '\u{0}' as i32 as libc::c_char;
|
|
|
|
buf
|
|
}
|
|
|
|
pub unsafe fn dc_decode_ext_header(to_decode: *const libc::c_char) -> *mut libc::c_char {
|
|
let mut decoded: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut charset: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
let mut p2: *const libc::c_char;
|
|
if !to_decode.is_null() {
|
|
// get char set
|
|
p2 = strchr(to_decode, '\'' as i32);
|
|
if !(p2.is_null() || p2 == to_decode) {
|
|
/*no empty charset allowed*/
|
|
charset =
|
|
dc_null_terminate(to_decode, p2.wrapping_offset_from(to_decode) as libc::c_int);
|
|
p2 = p2.offset(1isize);
|
|
// skip language
|
|
p2 = strchr(p2, '\'' as i32);
|
|
if !p2.is_null() {
|
|
p2 = p2.offset(1isize);
|
|
decoded = dc_urldecode(p2);
|
|
if !charset.is_null()
|
|
&& strcmp(charset, b"utf-8\x00" as *const u8 as *const libc::c_char) != 0i32
|
|
&& strcmp(charset, b"UTF-8\x00" as *const u8 as *const libc::c_char) != 0i32
|
|
{
|
|
if let Some(encoding) =
|
|
Charset::for_label(CStr::from_ptr(charset).to_str().unwrap().as_bytes())
|
|
{
|
|
let data =
|
|
std::slice::from_raw_parts(decoded as *const u8, strlen(decoded));
|
|
|
|
let (res, _, _) = encoding.decode(data);
|
|
free(decoded as *mut _);
|
|
let r = std::ffi::CString::new(res.as_bytes()).unwrap();
|
|
decoded = dc_strdup(r.as_ptr());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(charset as *mut libc::c_void);
|
|
return if !decoded.is_null() {
|
|
decoded
|
|
} else {
|
|
dc_strdup(to_decode)
|
|
};
|
|
}
|
|
|
|
unsafe fn print_hex(target: *mut libc::c_char, cur: *const libc::c_char) {
|
|
assert!(!target.is_null());
|
|
assert!(!cur.is_null());
|
|
|
|
let bytes = std::slice::from_raw_parts(cur as *const _, strlen(cur));
|
|
let raw = to_cstring(format!("={}", &hex::encode_upper(bytes)[..2]));
|
|
libc::memcpy(target as *mut _, raw as *const _, 4);
|
|
free(raw as *mut libc::c_void);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::ffi::CStr;
|
|
|
|
#[test]
|
|
fn test_isalnum() {
|
|
assert_eq!(isalnum(0), 0);
|
|
assert_eq!(isalnum('5' as libc::c_int), 1);
|
|
assert_eq!(isalnum('Q' as libc::c_int), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_dc_decode_header_words() {
|
|
unsafe {
|
|
let mut buf1: *mut libc::c_char = dc_decode_header_words(
|
|
b"=?utf-8?B?dGVzdMOkw7bDvC50eHQ=?=\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf1,
|
|
b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\x00" as *const u8 as *const libc::c_char
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 =
|
|
dc_decode_header_words(b"just ascii test\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "just ascii test");
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_encode_header_words(b"abcdef\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(CStr::from_ptr(buf1).to_str().unwrap(), "abcdef");
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_encode_header_words(
|
|
b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
assert_eq!(
|
|
strncmp(buf1, b"=?utf-8\x00" as *const u8 as *const libc::c_char, 7),
|
|
0
|
|
);
|
|
|
|
let buf2: *mut libc::c_char = dc_decode_header_words(buf1);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf2,
|
|
b"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\x00" as *const u8 as *const libc::c_char
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
free(buf2 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_header_words(
|
|
b"=?ISO-8859-1?Q?attachment=3B=0D=0A_filename=3D?= =?ISO-8859-1?Q?=22test=E4=F6=FC=2Etxt=22=3B=0D=0A_size=3D39?=\x00" as *const u8 as *const libc::c_char
|
|
);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf1,
|
|
b"attachment;\r\n filename=\"test\xc3\xa4\xc3\xb6\xc3\xbc.txt\";\r\n size=39\x00" as *const u8 as *const libc::c_char,
|
|
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_dc_encode_ext_header() {
|
|
unsafe {
|
|
let mut buf1 = dc_encode_ext_header(
|
|
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
assert_eq!(
|
|
CStr::from_ptr(buf1).to_str().unwrap(),
|
|
"utf-8\'\'Bj%C3%B6rn%20Petersen"
|
|
);
|
|
let buf2 = dc_decode_ext_header(buf1);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf2,
|
|
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char,
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
free(buf2 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(
|
|
b"iso-8859-1\'en\'%A3%20rates\x00" as *const u8 as *const libc::c_char,
|
|
);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf1,
|
|
b"\xc2\xa3 rates\x00" as *const u8 as *const libc::c_char,
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(b"wrong\'format\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(
|
|
strcmp(
|
|
buf1,
|
|
b"wrong\'format\x00" as *const u8 as *const libc::c_char,
|
|
),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(b"\'\'\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(
|
|
strcmp(buf1, b"\'\'\x00" as *const u8 as *const libc::c_char),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(b"x\'\'\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(strcmp(buf1, b"\x00" as *const u8 as *const libc::c_char), 0);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(b"\'\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(
|
|
strcmp(buf1, b"\'\x00" as *const u8 as *const libc::c_char),
|
|
0
|
|
);
|
|
free(buf1 as *mut libc::c_void);
|
|
|
|
buf1 = dc_decode_ext_header(b"\x00" as *const u8 as *const libc::c_char);
|
|
assert_eq!(strcmp(buf1, b"\x00" as *const u8 as *const libc::c_char), 0);
|
|
free(buf1 as *mut libc::c_void);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_dc_needs_ext_header() {
|
|
unsafe {
|
|
assert_eq!(
|
|
dc_needs_ext_header(b"Bj\xc3\xb6rn\x00" as *const u8 as *const libc::c_char),
|
|
true
|
|
);
|
|
assert_eq!(
|
|
dc_needs_ext_header(b"Bjoern\x00" as *const u8 as *const libc::c_char),
|
|
false
|
|
);
|
|
assert_eq!(
|
|
dc_needs_ext_header(b"\x00" as *const u8 as *const libc::c_char),
|
|
false
|
|
);
|
|
assert_eq!(
|
|
dc_needs_ext_header(b" \x00" as *const u8 as *const libc::c_char),
|
|
true
|
|
);
|
|
assert_eq!(
|
|
dc_needs_ext_header(b"a b\x00" as *const u8 as *const libc::c_char),
|
|
true
|
|
);
|
|
assert_eq!(
|
|
dc_needs_ext_header(0 as *const u8 as *const libc::c_char),
|
|
false
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_print_hex() {
|
|
let mut hex: [libc::c_char; 4] = [0; 4];
|
|
let cur = b"helloworld" as *const u8 as *const libc::c_char;
|
|
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
|
assert_eq!(to_string(hex.as_ptr() as *const _), "=68");
|
|
|
|
let cur = b":" as *const u8 as *const libc::c_char;
|
|
unsafe { print_hex(hex.as_mut_ptr(), cur) };
|
|
assert_eq!(to_string(hex.as_ptr() as *const _), "=3A");
|
|
}
|
|
|
|
#[test]
|
|
fn test_dc_urlencode_urldecode() {
|
|
unsafe {
|
|
let buf1 =
|
|
dc_urlencode(b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char);
|
|
|
|
assert_eq!(
|
|
CStr::from_ptr(buf1 as *const libc::c_char)
|
|
.to_str()
|
|
.unwrap(),
|
|
"Bj%C3%B6rn+Petersen"
|
|
);
|
|
|
|
let buf2 = dc_urldecode(buf1);
|
|
|
|
assert_eq!(
|
|
strcmp(
|
|
buf2,
|
|
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char
|
|
),
|
|
0
|
|
);
|
|
|
|
free(buf1 as *mut libc::c_void);
|
|
free(buf2 as *mut libc::c_void);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_dc_encode_decode_modified_utf7() {
|
|
unsafe {
|
|
let buf1 = dc_encode_modified_utf7(
|
|
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char,
|
|
1,
|
|
);
|
|
|
|
assert_eq!(
|
|
CStr::from_ptr(buf1 as *const libc::c_char)
|
|
.to_str()
|
|
.unwrap(),
|
|
"Bj&APY-rn_Petersen"
|
|
);
|
|
|
|
let buf2 = dc_decode_modified_utf7(buf1, 1);
|
|
|
|
assert_eq!(
|
|
strcmp(
|
|
buf2,
|
|
b"Bj\xc3\xb6rn Petersen\x00" as *const u8 as *const libc::c_char
|
|
),
|
|
0
|
|
);
|
|
|
|
free(buf1 as *mut libc::c_void);
|
|
free(buf2 as *mut libc::c_void);
|
|
}
|
|
}
|
|
#[test]
|
|
fn test_hex_to_int() {
|
|
assert_eq!(hex_2_int(b'A' as libc::c_char), 10);
|
|
assert_eq!(hex_2_int(b'a' as libc::c_char), 10);
|
|
assert_eq!(hex_2_int(b'4' as libc::c_char), 4);
|
|
assert_eq!(hex_2_int(b'K' as libc::c_char), 20);
|
|
}
|
|
}
|