diff --git a/Cargo.lock b/Cargo.lock index c0c9c9043..a588114d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,6 +199,11 @@ name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytecount" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.2" @@ -223,6 +228,18 @@ dependencies = [ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cargo_metadata" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cast5" version = "0.6.0" @@ -457,6 +474,7 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -742,6 +760,11 @@ dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "h2" version = "0.1.26" @@ -887,6 +910,16 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "image-meta" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "imap" version = "1.0.2" @@ -1567,6 +1600,14 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -1910,6 +1951,14 @@ name = "safemem" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "same-file" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "schannel" version = "0.1.15" @@ -1967,6 +2016,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2052,6 +2102,21 @@ name = "siphasher" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "skeptic" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.2" @@ -2490,6 +2555,16 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "2.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "want" version = "0.2.0" @@ -2633,9 +2708,11 @@ dependencies = [ "checksum buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" "checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cast5 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ce5759b4c52ca74f9a98421817c882f1fd9b0071ae41cd61ab9f9d059c04fd6" "checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cfb-mode 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "190e7b55d3a27cf8879becf61035a141cbc783f3258a41d16d1706719f991345" @@ -2691,6 +2768,7 @@ dependencies = [ "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8e190892c840661957ba9f32dacfb3eb405e657f9f9f60485605f0bb37d6f8" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -2704,6 +2782,7 @@ dependencies = [ "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b00861cbbb254a627d8acc0cec786b484297d896ab8f20fdc8e28536a3e918ef" "checksum imap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "178392198cb2716f4fe34b86a1bf1de1240a3e31136a199b16490fa87538fa25" "checksum imap-proto 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4e77b1d61faf028893531b071cc5584cdd02b6186cebe7f7168ffd8d591339a" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -2775,6 +2854,7 @@ dependencies = [ "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" +"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum r2d2 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bc42ce75d9f4447fb2a04bbe1ed5d18dd949104572850ec19b164e274919f81b" @@ -2809,6 +2889,7 @@ dependencies = [ "checksum rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f47ea1ceb347d2deae482d655dc8eef4bd82363d3329baffa3818bd76fea48b" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum safemem 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e133ccc4f4d1cd4f89cc8a7ff618287d56dc7f638b8e38fc32c5fdcadc339dd5" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scheduled-thread-pool 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd07742e081ff6c077f5f6b283f12f32b9e7cc765b316160d66289b74546fbb3" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" @@ -2826,6 +2907,7 @@ dependencies = [ "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffddf594f5f597f63533d897427a570dbaa9feabaaa06595b74b71b7014507d7" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" @@ -2879,6 +2961,7 @@ dependencies = [ "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" diff --git a/Cargo.toml b/Cargo.toml index 36ae398fa..d58e47b2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ thread-local-object = "0.1.0" backtrace = "0.3.33" byteorder = "1.3.1" itertools = "0.8.0" +image-meta = "0.1.0" [dev-dependencies] tempfile = "3.0" diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index afe01bea3..0aca18d74 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -1126,20 +1126,10 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E } "fileinfo" => { ensure!(!arg1.is_empty(), "Argument missing."); - let mut buf = 0 as *mut libc::c_uchar; - let mut buf_bytes = 0; - let mut w = 0; - let mut h = 0; - if 0 != dc_read_file( - context, - arg1_c, - &mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void, - &mut buf_bytes, - ) { - dc_get_filemeta(buf as *const libc::c_void, buf_bytes, &mut w, &mut h); - println!("width={}, height={}", w, h,); - free(buf as *mut libc::c_void); + if let Some(buf) = dc_read_file_safe(context, &arg1) { + let (width, height) = dc_get_filemeta(&buf)?; + println!("width={}, height={}", width, height); } else { bail!("Command failed."); } diff --git a/src/dc_job.rs b/src/dc_job.rs index d35565808..9143f9d22 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -1036,43 +1036,25 @@ pub unsafe fn dc_job_send_msg(context: &Context, msg_id: uint32_t) -> libc::c_in } else { // no redo, no IMAP. moreover, as the data does not exist, there is no need in calling dc_set_msg_failed() if msgtype_has_file((*mimefactory.msg).type_0) { - let pathNfilename = (*mimefactory.msg) - .param - .get(Param::File) - .unwrap_or_default() - .strdup(); - if strlen(pathNfilename) > 0 { + if let Some(pathNfilename) = (*mimefactory.msg).param.get(Param::File) { if ((*mimefactory.msg).type_0 == Viewtype::Image || (*mimefactory.msg).type_0 == Viewtype::Gif) && !(*mimefactory.msg).param.exists(Param::Width) { - let mut buf = 0 as *mut libc::c_uchar; - let mut buf_bytes: size_t = 0; - let mut w = 0; - let mut h = 0; (*mimefactory.msg).param.set_int(Param::Width, 0); (*mimefactory.msg).param.set_int(Param::Height, 0); - if 0 != dc_read_file( - context, - pathNfilename, - &mut buf as *mut *mut libc::c_uchar as *mut *mut libc::c_void, - &mut buf_bytes, - ) { - if 0 != dc_get_filemeta( - buf as *const libc::c_void, - buf_bytes, - &mut w, - &mut h, - ) { - (*mimefactory.msg).param.set_int(Param::Width, w as i32); - (*mimefactory.msg).param.set_int(Param::Height, h as i32); + + if let Some(buf) = dc_read_file_safe(context, pathNfilename) { + if let Ok((width, height)) = dc_get_filemeta(&buf) { + (*mimefactory.msg).param.set_int(Param::Width, width as i32); + (*mimefactory.msg) + .param + .set_int(Param::Height, height as i32); } } - free(buf as *mut libc::c_void); dc_msg_save_param_to_disk(mimefactory.msg); } } - free(pathNfilename as *mut libc::c_void); } /* create message */ if 0 == dc_mimefactory_render(&mut mimefactory) { diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index d0acb1364..806f74841 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -1415,16 +1415,15 @@ unsafe fn do_add_single_file_part( part.param.set(Param::File, as_str(pathNfilename)); part.param.set(Param::MimeType, as_str(raw_mime)); if mime_type == 80 { - let mut w = 0; - let mut h = 0; - if 0 != dc_get_filemeta( - decoded_data as *const libc::c_void, - decoded_data_bytes, - &mut w, - &mut h, - ) { - part.param.set_int(Param::Width, w as i32); - part.param.set_int(Param::Height, h as i32); + assert!(!decoded_data.is_null(), "invalid image data"); + let data = std::slice::from_raw_parts( + decoded_data as *const u8, + decoded_data_bytes as usize, + ); + + if let Ok((width, height)) = dc_get_filemeta(data) { + part.param.set_int(Param::Width, width as i32); + part.param.set_int(Param::Height, height as i32); } } do_add_single_part(parser, part); diff --git a/src/dc_tools.rs b/src/dc_tools.rs index d18cd3d69..0c8d8b479 100644 --- a/src/dc_tools.rs +++ b/src/dc_tools.rs @@ -1,9 +1,8 @@ use std::borrow::Cow; use std::ffi::{CStr, CString}; -use std::fmt; -use std::fs; use std::str::FromStr; use std::time::SystemTime; +use std::{fmt, fs, ptr}; use chrono::{Local, TimeZone}; use mmime::mailimf_types::*; @@ -14,16 +13,15 @@ use crate::dc_array::*; use crate::error::Error; use crate::types::*; use crate::x::*; -use std::ptr; -const ELLIPSE: &'static str = "[...]"; +const ELLIPSE: &str = "[...]"; /* Some tools and enhancements to the used libraries, there should be no references to Context and other "larger" classes here. */ /* ** library-private **********************************************************/ /* math tools */ pub fn dc_exactly_one_bit_set(v: libc::c_int) -> bool { - 0 != v && 0 == v & v - 1i32 + 0 != v && 0 == v & (v - 1) } /// Duplicates a string @@ -110,7 +108,7 @@ pub unsafe fn dc_str_replace( pub unsafe fn dc_ftoa(f: libc::c_double) -> *mut libc::c_char { // hack around printf(%f) that may return `,` as decimal point on mac let test: *mut libc::c_char = dc_mprintf(b"%f\x00" as *const u8 as *const libc::c_char, 1.2f64); - *test.offset(2isize) = 0i32 as libc::c_char; + *test.offset(2isize) = 0 as libc::c_char; let mut str: *mut libc::c_char = dc_mprintf(b"%f\x00" as *const u8 as *const libc::c_char, f); dc_str_replace( &mut str, @@ -156,9 +154,9 @@ pub unsafe fn dc_rtrim(buf: *mut libc::c_char) { } *cur.offset( (if 0 != libc::isspace(*cur as libc::c_int) { - 0i32 + 0 } else { - 1i32 + 1 }) as isize, ) = '\u{0}' as i32 as libc::c_uchar }; @@ -185,17 +183,17 @@ pub unsafe fn dc_str_contains( needle: *const libc::c_char, ) -> libc::c_int { if haystack.is_null() || needle.is_null() { - return 0i32; + return 0; } if !strstr(haystack, needle).is_null() { - return 1i32; + return 1; } let haystack_lower: *mut libc::c_char = dc_strlower(haystack); let needle_lower: *mut libc::c_char = dc_strlower(needle); - let ret: libc::c_int = if !strstr(haystack_lower, needle_lower).is_null() { - 1i32 + let ret = if !strstr(haystack_lower, needle_lower).is_null() { + 1 } else { - 0i32 + 0 }; free(haystack_lower as *mut libc::c_void); free(needle_lower as *mut libc::c_void); @@ -210,10 +208,10 @@ pub unsafe fn dc_null_terminate( ) -> *mut libc::c_char { let out: *mut libc::c_char = malloc(bytes as usize + 1) as *mut libc::c_char; assert!(!out.is_null()); - if !in_0.is_null() && bytes > 0i32 { + if !in_0.is_null() && bytes > 0 { strncpy(out, in_0, bytes as usize); } - *out.offset(bytes as isize) = 0i32 as libc::c_char; + *out.offset(bytes as isize) = 0 as libc::c_char; out } @@ -247,7 +245,7 @@ pub unsafe fn dc_remove_cr_chars(buf: *mut libc::c_char) { } p1 = p1.offset(1isize) } - *p2 = 0i32 as libc::c_char; + *p2 = 0 as libc::c_char; } pub unsafe fn dc_unify_lineends(buf: *mut libc::c_char) { @@ -269,39 +267,39 @@ pub unsafe fn dc_replace_bad_utf8_chars(buf: *mut libc::c_char) { let ix: libc::c_int; let mut n: libc::c_int; let mut j: libc::c_int; - i = 0i32; + i = 0; ix = p1len; 's_36: loop { if !(i < ix) { break; } c = *p1.offset(i as isize) as libc::c_int; - if c > 0i32 && c <= 0x7fi32 { - n = 0i32 - } else if c & 0xe0i32 == 0xc0i32 { - n = 1i32 - } else if c == 0xedi32 - && i < ix - 1i32 - && *p1.offset((i + 1i32) as isize) as libc::c_int & 0xa0i32 == 0xa0i32 + if c > 0 && c <= 0x7f { + n = 0 + } else if c & 0xe0 == 0xc0 { + n = 1 + } else if c == 0xed + && i < ix - 1 + && *p1.offset((i + 1) as isize) as libc::c_int & 0xa0 == 0xa0 { /* U+d800 to U+dfff */ OK_TO_CONTINUE = false; break; - } else if c & 0xf0i32 == 0xe0i32 { - n = 2i32 - } else if c & 0xf8i32 == 0xf0i32 { - n = 3i32 + } else if c & 0xf0 == 0xe0 { + n = 2 + } else if c & 0xf8 == 0xf0 { + n = 3 } else { //else if ((c & 0xFC) == 0xF8) { n=4; } /* 111110bb - not valid in https://tools.ietf.org/html/rfc3629 */ //else if ((c & 0xFE) == 0xFC) { n=5; } /* 1111110b - not valid in https://tools.ietf.org/html/rfc3629 */ OK_TO_CONTINUE = false; break; } - j = 0i32; + j = 0; while j < n && i < ix { /* n bytes matching 10bbbbbb follow ? */ i += 1; - if i == ix || *p1.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + if i == ix || *p1.offset(i as isize) as libc::c_int & 0xc0 != 0x80 { OK_TO_CONTINUE = false; break 's_36; } @@ -311,7 +309,7 @@ pub unsafe fn dc_replace_bad_utf8_chars(buf: *mut libc::c_char) { } if OK_TO_CONTINUE == false { while 0 != *p1 { - if *p1 as libc::c_int > 0x7fi32 { + if *p1 as libc::c_int > 0x7f { *p1 = '_' as i32 as libc::c_uchar } p1 = p1.offset(1isize) @@ -322,15 +320,17 @@ pub unsafe fn dc_replace_bad_utf8_chars(buf: *mut libc::c_char) { pub unsafe fn dc_utf8_strlen(s: *const libc::c_char) -> size_t { if s.is_null() { - return 0i32 as size_t; + return 0; } - let mut i: size_t = 0i32 as size_t; - let mut j: size_t = 0i32 as size_t; - while 0 != *s.offset(i as isize) { - if *s.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + + let mut i = 0; + let mut j: size_t = 0; + + while 0 != *s.add(i) { + if *s.offset(i as isize) as libc::c_int & 0xc0 != 0x80 { j = j.wrapping_add(1) } - i = i.wrapping_add(1) + i += 1; } j @@ -363,12 +363,12 @@ pub unsafe fn dc_truncate_n_unwrap_str( } else { b" [...]\x00" as *const u8 as *const libc::c_char }; - let mut lastIsCharacter: libc::c_int = 0i32; + let mut lastIsCharacter: libc::c_int = 0; /* force unsigned - otherwise the `> ' '` comparison will fail */ let mut p1: *mut libc::c_uchar = buf as *mut libc::c_uchar; while 0 != *p1 { if *p1 as libc::c_int > ' ' as i32 { - lastIsCharacter = 1i32 + lastIsCharacter = 1 } else if 0 != lastIsCharacter { let used_bytes: size_t = (p1 as uintptr_t).wrapping_sub(buf as uintptr_t) as size_t; if dc_utf8_strnlen(buf, used_bytes) >= approx_characters as usize { @@ -378,7 +378,7 @@ pub unsafe fn dc_truncate_n_unwrap_str( } break; } else { - lastIsCharacter = 0i32; + lastIsCharacter = 0; if 0 != do_unwrap { *p1 = ' ' as i32 as libc::c_uchar } @@ -395,15 +395,14 @@ pub unsafe fn dc_truncate_n_unwrap_str( unsafe fn dc_utf8_strnlen(s: *const libc::c_char, n: size_t) -> size_t { if s.is_null() { - return 0i32 as size_t; + return 0; } - let mut i: size_t = 0i32 as size_t; - let mut j: size_t = 0i32 as size_t; - while i < n { - if *s.offset(i as isize) as libc::c_int & 0xc0i32 != 0x80i32 { + + let mut j: size_t = 0; + for i in 0..n { + if *s.add(i) as libc::c_int & 0xc0 != 0x80 { j = j.wrapping_add(1) } - i = i.wrapping_add(1) } j @@ -442,7 +441,7 @@ pub unsafe fn dc_insert_breaks( break_every: libc::c_int, break_chars: *const libc::c_char, ) -> *mut libc::c_char { - if in_0.is_null() || break_every <= 0i32 || break_chars.is_null() { + if in_0.is_null() || break_every <= 0 || break_chars.is_null() { return dc_strdup(in_0); } let mut out_len = strlen(in_0); @@ -451,7 +450,7 @@ pub unsafe fn dc_insert_breaks( out_len += (out_len / break_every as usize + 1) * break_chars_len + 1; let out: *mut libc::c_char = malloc(out_len) as *mut libc::c_char; if out.is_null() { - return 0 as *mut libc::c_char; + return ptr::null_mut(); } let mut i: *const libc::c_char = in_0; let mut o: *mut libc::c_char = out; @@ -464,11 +463,11 @@ pub unsafe fn dc_insert_breaks( chars_added += 1; if chars_added == break_every && 0 != *i as libc::c_int { strcpy(o, break_chars); - o = o.offset(break_chars_len as isize); - chars_added = 0i32 + o = o.add(break_chars_len); + chars_added = 0 } } - *o = 0i32 as libc::c_char; + *o = 0 as libc::c_char; out } @@ -485,7 +484,7 @@ pub unsafe fn dc_str_from_clist( let rfc724_mid = (if !cur.is_null() { (*cur).data } else { - 0 as *mut libc::c_void + ptr::null_mut() }) as *const libc::c_char; if !rfc724_mid.is_null() { @@ -497,7 +496,7 @@ pub unsafe fn dc_str_from_clist( cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell + ptr::null_mut() } } } @@ -525,7 +524,7 @@ pub unsafe fn dc_str_to_clist( (*list).last, strndup(p1, p2.wrapping_offset_from(p1) as libc::c_ulong) as *mut libc::c_void, ); - p1 = p2.offset(strlen(delimiter) as isize) + p1 = p2.add(strlen(delimiter)) } } } @@ -548,8 +547,8 @@ pub fn dc_str_to_color_safe(s: impl AsRef) -> u32 { let str_lower = s.as_ref().to_lowercase(); let mut checksum = 0; let bytes = str_lower.as_bytes(); - for i in 0..str_lower.len() { - checksum += (i + 1) * bytes[i] as usize; + for (i, byte) in bytes.iter().enumerate() { + checksum += (i + 1) * *byte as usize; checksum %= 0xffffff; } let color_index = checksum % COLORS.len(); @@ -558,15 +557,14 @@ pub fn dc_str_to_color_safe(s: impl AsRef) -> u32 { } pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int { - let str_lower: *mut libc::c_char = dc_strlower(str); - let mut checksum: libc::c_int = 0i32; - let str_len: libc::c_int = strlen(str_lower) as libc::c_int; - let mut i: libc::c_int = 0i32; - while i < str_len { - checksum += (i + 1i32) * *str_lower.offset(i as isize) as libc::c_int; - checksum %= 0xffffffi32; - i += 1 + let str_lower = dc_strlower(str); + let mut checksum = 0; + let str_len = strlen(str_lower) as usize; + for i in 0..str_len { + checksum += (i + 1) * *str_lower.add(i) as usize; + checksum %= 0xffffff; } + let color_index: libc::c_int = (checksum as libc::c_ulong).wrapping_rem( (::std::mem::size_of::<[uint32_t; 16]>() as libc::c_ulong) .wrapping_div(::std::mem::size_of::() as libc::c_ulong), @@ -579,14 +577,15 @@ pub unsafe fn dc_str_to_color(str: *const libc::c_char) -> libc::c_int { /* clist tools */ /* calls free() for each item content */ pub unsafe fn clist_free_content(haystack: *const clist) { - let mut iter: *mut clistiter = (*haystack).first; + let mut iter = (*haystack).first; + while !iter.is_null() { free((*iter).data); - (*iter).data = 0 as *mut libc::c_void; + (*iter).data = ptr::null_mut(); iter = if !iter.is_null() { (*iter).next } else { - 0 as *mut clistcell + ptr::null_mut() } } } @@ -595,15 +594,16 @@ pub unsafe fn clist_search_string_nocase( haystack: *const clist, needle: *const libc::c_char, ) -> libc::c_int { - let mut iter: *mut clistiter = (*haystack).first; + let mut iter = (*haystack).first; + while !iter.is_null() { - if strcasecmp((*iter).data as *const libc::c_char, needle) == 0i32 { - return 1i32; + if strcasecmp((*iter).data as *const libc::c_char, needle) == 0 { + return 1; } iter = if !iter.is_null() { (*iter).next } else { - 0 as *mut clistcell + ptr::null_mut() } } @@ -626,11 +626,11 @@ pub unsafe fn dc_timestamp_from_date(date_time: *mut mailimf_date_time) -> i64 { ); let (zone_hour, zone_min) = if (*date_time).dt_zone >= 0 { - ((*date_time).dt_zone / 100i32, (*date_time).dt_zone % 100i32) + ((*date_time).dt_zone / 100, (*date_time).dt_zone % 100) } else { ( - -(-(*date_time).dt_zone / 100i32), - -(-(*date_time).dt_zone % 100i32), + -(-(*date_time).dt_zone / 100), + -(-(*date_time).dt_zone % 100), ) }; @@ -738,12 +738,12 @@ pub unsafe fn dc_create_incoming_rfc724_mid( contact_ids_to: *mut dc_array_t, ) -> *mut libc::c_char { if contact_ids_to.is_null() || dc_array_get_cnt(contact_ids_to) == 0 { - return 0 as *mut libc::c_char; + return ptr::null_mut(); } /* find out the largest receiver ID (we could also take the smallest, but it should be unique) */ - let mut i: size_t = 0i32 as size_t; - let icnt: size_t = dc_array_get_cnt(contact_ids_to); - let mut largest_id_to: uint32_t = 0i32 as uint32_t; + let mut i = 0; + let icnt = dc_array_get_cnt(contact_ids_to); + let mut largest_id_to = 0; while i < icnt { let cur_id: uint32_t = dc_array_get_id(contact_ids_to, i); if cur_id > largest_id_to { @@ -768,7 +768,7 @@ pub unsafe fn dc_create_outgoing_rfc724_mid( - this function is called for all outgoing messages. - the message ID should be globally unique - do not add a counter or any private data as as this may give unneeded information to the receiver */ - let mut rand1: *mut libc::c_char = 0 as *mut libc::c_char; + let mut rand1: *mut libc::c_char = ptr::null_mut(); let rand2: *mut libc::c_char = dc_create_id().strdup(); let ret: *mut libc::c_char; let mut at_hostname: *const libc::c_char = strchr(from_addr, '@' as i32); @@ -844,25 +844,22 @@ pub unsafe fn dc_extract_grpid_from_rfc724_mid_list(list: *const clist) -> *mut cur = if !cur.is_null() { (*cur).next } else { - 0 as *mut clistcell + ptr::null_mut() } } } - 0 as *mut libc::c_char + ptr::null_mut() } -/* file tools */ #[allow(non_snake_case)] pub unsafe fn dc_ensure_no_slash(pathNfilename: *mut libc::c_char) { let path_len = strlen(pathNfilename); - if path_len > 0 { - if *pathNfilename.offset((path_len - 1) as isize) as libc::c_int == '/' as i32 - || *pathNfilename.offset((path_len - 1) as isize) as libc::c_int == '\\' as i32 - { - *pathNfilename.offset((path_len - 1) as isize) = 0 as libc::c_char - } - }; + if path_len > 0 && *pathNfilename.add(path_len - 1) as libc::c_int == '/' as i32 + || *pathNfilename.add(path_len - 1) as libc::c_int == '\\' as i32 + { + *pathNfilename.add(path_len - 1) = 0 as libc::c_char; + } } pub fn dc_ensure_no_slash_safe(path: &str) -> &str { @@ -917,9 +914,9 @@ pub unsafe fn dc_split_filename( let p1: *mut libc::c_char = strrchr(basename, '.' as i32); if !p1.is_null() { suffix = dc_strdup(p1); - *p1 = 0i32 as libc::c_char + *p1 = 0 as libc::c_char } else { - suffix = dc_strdup(0 as *const libc::c_char) + suffix = dc_strdup(ptr::null()) } if !ret_basename.is_null() { *ret_basename = basename @@ -944,90 +941,14 @@ pub unsafe fn dc_get_filesuffix_lc(pathNfilename: *const libc::c_char) -> *mut l } } - 0 as *mut libc::c_char + ptr::null_mut() } -pub unsafe fn dc_get_filemeta( - buf_start: *const libc::c_void, - buf_bytes: size_t, - ret_width: *mut uint32_t, - ret_height: *mut uint32_t, -) -> libc::c_int { - /* Strategy: - reading GIF dimensions requires the first 10 bytes of the file - reading PNG dimensions requires the first 24 bytes of the file - reading JPEG dimensions requires scanning through jpeg chunks - In all formats, the file is at least 24 bytes big, so we'll read that always - inspired by http://www.cplusplus.com/forum/beginner/45217/ */ - let buf: *const libc::c_uchar = buf_start as *const libc::c_uchar; - if buf_bytes < 24 { - return 0i32; - } - if *buf.offset(0isize) as libc::c_int == 0xffi32 - && *buf.offset(1isize) as libc::c_int == 0xd8i32 - && *buf.offset(2isize) as libc::c_int == 0xffi32 - { - let mut pos = 2; - while *buf.offset(pos as isize) as libc::c_int == 0xffi32 { - if *buf.offset((pos + 1) as isize) as libc::c_int == 0xc0i32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xc1i32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xc2i32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xc3i32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xc9i32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xcai32 - || *buf.offset((pos + 1) as isize) as libc::c_int == 0xcbi32 - { - *ret_height = (((*buf.offset((pos + 5) as isize) as libc::c_int) << 8i32) - + *buf.offset((pos + 6) as isize) as libc::c_int) - as uint32_t; - *ret_width = (((*buf.offset((pos + 7) as isize) as libc::c_int) << 8i32) - + *buf.offset((pos + 8) as isize) as libc::c_int) - as uint32_t; - return 1i32; - } - pos += 2 - + ((*buf.offset((pos + 2) as isize) as libc::c_int) << 8) - + *buf.offset((pos + 3) as isize) as libc::c_int; - if (pos + 12) > buf_bytes as libc::c_int { - break; - } - } - } - if *buf.offset(0isize) as libc::c_int == 'G' as i32 - && *buf.offset(1isize) as libc::c_int == 'I' as i32 - && *buf.offset(2isize) as libc::c_int == 'F' as i32 - { - *ret_width = (*buf.offset(6isize) as libc::c_int - + ((*buf.offset(7isize) as libc::c_int) << 8i32)) as uint32_t; - *ret_height = (*buf.offset(8isize) as libc::c_int - + ((*buf.offset(9isize) as libc::c_int) << 8i32)) as uint32_t; - return 1i32; - } - if *buf.offset(0isize) as libc::c_int == 0x89i32 - && *buf.offset(1isize) as libc::c_int == 'P' as i32 - && *buf.offset(2isize) as libc::c_int == 'N' as i32 - && *buf.offset(3isize) as libc::c_int == 'G' as i32 - && *buf.offset(4isize) as libc::c_int == 0xdi32 - && *buf.offset(5isize) as libc::c_int == 0xai32 - && *buf.offset(6isize) as libc::c_int == 0x1ai32 - && *buf.offset(7isize) as libc::c_int == 0xai32 - && *buf.offset(12isize) as libc::c_int == 'I' as i32 - && *buf.offset(13isize) as libc::c_int == 'H' as i32 - && *buf.offset(14isize) as libc::c_int == 'D' as i32 - && *buf.offset(15isize) as libc::c_int == 'R' as i32 - { - *ret_width = (((*buf.offset(16isize) as libc::c_int) << 24i32) - + ((*buf.offset(17isize) as libc::c_int) << 16i32) - + ((*buf.offset(18isize) as libc::c_int) << 8i32) - + ((*buf.offset(19isize) as libc::c_int) << 0i32)) as uint32_t; - *ret_height = (((*buf.offset(20isize) as libc::c_int) << 24i32) - + ((*buf.offset(21isize) as libc::c_int) << 16i32) - + ((*buf.offset(22isize) as libc::c_int) << 8i32) - + ((*buf.offset(23isize) as libc::c_int) << 0i32)) as uint32_t; - return 1i32; - } +/// Returns the `(width, height)` of the given image buffer. +pub fn dc_get_filemeta(buf: &[u8]) -> Result<(u32, u32), Error> { + let meta = image_meta::load_from_buf(buf)?; - 0 + Ok((meta.dimensions.width, meta.dimensions.height)) } /// Expand paths relative to $BLOBDIR into absolute paths. @@ -1056,17 +977,17 @@ pub unsafe fn dc_get_abs_path( pathNfilename: *const libc::c_char, ) -> *mut libc::c_char { if pathNfilename.is_null() { - return 0 as *mut libc::c_char; + return ptr::null_mut(); } let starts = strncmp( pathNfilename, b"$BLOBDIR\x00" as *const u8 as *const libc::c_char, 8, - ) == 0i32; + ) == 0; if starts && !context.has_blobdir() { - return 0 as *mut libc::c_char; + return ptr::null_mut(); } let mut pathNfilename_abs: *mut libc::c_char = dc_strdup(pathNfilename); @@ -1225,22 +1146,23 @@ pub unsafe fn dc_get_fine_pathNfilename( pathNfolder: *const libc::c_char, desired_filenameNsuffix__: *const libc::c_char, ) -> *mut libc::c_char { - let mut ret: *mut libc::c_char = 0 as *mut libc::c_char; + let mut ret: *mut libc::c_char = ptr::null_mut(); let pathNfolder_wo_slash: *mut libc::c_char; let filenameNsuffix: *mut libc::c_char; - let mut basename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut dotNSuffix: *mut libc::c_char = 0 as *mut libc::c_char; + let mut basename: *mut libc::c_char = ptr::null_mut(); + let mut dotNSuffix: *mut libc::c_char = ptr::null_mut(); let now = time(); - let mut i: libc::c_int = 0i32; + pathNfolder_wo_slash = dc_strdup(pathNfolder); dc_ensure_no_slash(pathNfolder_wo_slash); filenameNsuffix = dc_strdup(desired_filenameNsuffix__); dc_validate_filename(filenameNsuffix); dc_split_filename(filenameNsuffix, &mut basename, &mut dotNSuffix); - while i < 1000i32 { + + for i in 0..1000i64 { /*no deadlocks, please*/ if 0 != i { - let idx = if i < 100 { i as i64 } else { now + i as i64 }; + let idx = if i < 100 { i } else { now + i }; ret = dc_mprintf( b"%s/%s-%lu%s\x00" as *const u8 as *const libc::c_char, pathNfolder_wo_slash, @@ -1259,12 +1181,11 @@ pub unsafe fn dc_get_fine_pathNfilename( if !dc_file_exist(context, as_path(ret)) { /* fine filename found */ break; - } else { - free(ret as *mut libc::c_void); - ret = 0 as *mut libc::c_char; - i += 1 } + free(ret as *mut libc::c_void); + ret = ptr::null_mut(); } + free(filenameNsuffix as *mut libc::c_void); free(basename as *mut libc::c_void); free(dotNSuffix as *mut libc::c_void); @@ -1282,7 +1203,7 @@ pub unsafe fn dc_make_rel_path(context: &Context, path: *mut *mut libc::c_char) if path.is_null() || (*path).is_null() { return; } - if strncmp(*path, context.get_blobdir(), strlen(context.get_blobdir())) == 0i32 { + if strncmp(*path, context.get_blobdir(), strlen(context.get_blobdir())) == 0 { dc_str_replace( path, context.get_blobdir(), @@ -1293,8 +1214,8 @@ pub unsafe fn dc_make_rel_path(context: &Context, path: *mut *mut libc::c_char) pub unsafe fn dc_make_rel_and_copy(context: &Context, path: *mut *mut libc::c_char) -> bool { let mut success = false; - let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; - let mut blobdir_path: *mut libc::c_char = 0 as *mut libc::c_char; + let mut filename: *mut libc::c_char = ptr::null_mut(); + let mut blobdir_path: *mut libc::c_char = ptr::null_mut(); if !(path.is_null() || (*path).is_null()) { if dc_is_blobdir_path(context, *path) { dc_make_rel_path(context, path); @@ -1799,7 +1720,7 @@ mod tests { unsafe { let str: *mut libc::c_char = dc_insert_breaks( b"just1234tes\x00" as *const u8 as *const libc::c_char, - 4i32, + 4, b"--\x00" as *const u8 as *const libc::c_char, ); assert_eq!( @@ -1815,7 +1736,7 @@ mod tests { unsafe { let str: *mut libc::c_char = dc_insert_breaks( b"just1234t\x00" as *const u8 as *const libc::c_char, - 4i32, + 4, b"\x00" as *const u8 as *const libc::c_char, ); assert_eq!( @@ -1831,7 +1752,7 @@ mod tests { unsafe { let str: *mut libc::c_char = dc_insert_breaks( b"\x00" as *const u8 as *const libc::c_char, - 4i32, + 4, b"---\x00" as *const u8 as *const libc::c_char, ); assert_eq!( @@ -1884,10 +1805,7 @@ mod tests { #[test] fn test_dc_str_to_clist_1() { unsafe { - let list: *mut clist = dc_str_to_clist( - 0 as *const libc::c_char, - b" \x00" as *const u8 as *const libc::c_char, - ); + let list = dc_str_to_clist(ptr::null(), b" \x00" as *const u8 as *const libc::c_char); assert_eq!((*list).count, 0); clist_free_content(list); clist_free(list); @@ -2006,7 +1924,7 @@ mod tests { #[test] fn test_dc_replace_bad_utf8_chars_4() { unsafe { - dc_replace_bad_utf8_chars(0 as *mut libc::c_char); + dc_replace_bad_utf8_chars(ptr::null_mut()); } } diff --git a/src/error.rs b/src/error.rs index 8f7855a4e..26f4700fd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,6 +18,8 @@ pub enum Error { Io(std::io::Error), #[fail(display = "{:?}", _0)] Message(String), + #[fail(display = "{:?}", _0)] + Image(image_meta::ImageError), } pub type Result = std::result::Result; @@ -46,6 +48,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: image_meta::ImageError) -> Error { + Error::Image(err) + } +} + #[macro_export] macro_rules! bail { ($e:expr) => {