#![allow(renamed_and_removed_lints)]
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate crypto;
extern crate serde;
extern crate serde_json;
use crypto::buffer::{ReadBuffer, WriteBuffer};
use crypto::{aes, blockmodes, buffer};
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;
use serde_json::{Value};
const ACCOUNT_KEY: [u8; 16] = [1, 6, 4, 5, 2, 7, 4, 3, 12, 61, 14, 75, 254, 249, 212, 33];
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct JdAccountList(HashMap<String, Vec<JdAccount>>);
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct JdAccount {
pub properties: Value,
pub hoster: String,
#[serde(rename = "maxSimultanDownloads")]
pub max_simultan_downloads: isize,
pub password : String,
#[serde(rename = "infoProperties")]
pub info_properties: Value,
#[serde(rename = "createTime")]
pub create_time: isize,
#[serde(rename = "trafficLeft")]
pub traffic_left: isize,
#[serde(rename = "trafficMax")]
pub traffic_max: isize,
#[serde(rename = "validUntil")]
pub valid_until: isize,
pub active: bool,
pub enabled: bool,
#[serde(rename = "trafficUnlimited")]
pub traffic_unlimited: bool,
pub specialtraffic: bool,
pub user: String,
#[serde(rename = "concurrentUsePossible")]
pub concurrent_use_possible: bool,
pub id: usize,
#[serde(rename = "errorType")]
pub error_type: Option<String>,
#[serde(rename = "errorString")]
pub error_string: Option<String>,
}
impl JdAccountList {
pub fn from_file<P: Into<String>>(path: P) -> Result<JdAccountList> {
let mut file = File::open(path.into())?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
JdAccountList::from_data(&data)
}
pub fn from_data(data: &[u8]) -> Result<JdAccountList> {
let mut data = decrypt_raw_data(data, &ACCOUNT_KEY, &ACCOUNT_KEY)?;
while data.last().ok_or("No decrypted data")? != &0x7Du8 {
data.pop().ok_or("No decrypted data in loop")?;
}
let data = std::str::from_utf8(&data)?;
let al: JdAccountList = serde_json::from_str(data)?;
Ok(al)
}
pub fn as_ref(&self) -> &HashMap<String, Vec<JdAccount>> {
&self.0
}
}
fn decrypt_raw_data(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
let mut decryptor = aes_cbc_decryptor(aes::KeySize::KeySize128, key, iv, blockmodes::NoPadding);
let mut buffer = [0; 4096];
let mut read_buffer = buffer::RefReadBuffer::new(data);
let mut writ_buffer = buffer::RefWriteBuffer::new(&mut buffer);
let mut result = Vec::new();
loop {
if decryptor
.decrypt(&mut read_buffer, &mut writ_buffer, true)
.is_err()
{
bail!("Can't decrypt");
}
if writ_buffer.is_empty() {
break;
}
result.extend_from_slice(writ_buffer.take_read_buffer().take_remaining());
}
result.retain(|x| *x != 0 as u8);
return Ok(result);
}
use crypto::aes::KeySize;
use crypto::aessafe;
use crypto::blockmodes::{CbcDecryptor, PaddingProcessor};
use crypto::symmetriccipher::Decryptor;
fn aes_cbc_decryptor<X: PaddingProcessor + Send + 'static>(
key_size: KeySize,
key: &[u8],
iv: &[u8],
padding: X,
) -> Box<Decryptor + 'static> {
match key_size {
KeySize::KeySize128 => {
let aes_dec = aessafe::AesSafe128Decryptor::new(key);
let dec = Box::new(CbcDecryptor::new(aes_dec, padding, iv.to_vec()));
dec as Box<Decryptor + 'static>
}
KeySize::KeySize192 => {
let aes_dec = aessafe::AesSafe192Decryptor::new(key);
let dec = Box::new(CbcDecryptor::new(aes_dec, padding, iv.to_vec()));
dec as Box<Decryptor + 'static>
}
KeySize::KeySize256 => {
let aes_dec = aessafe::AesSafe256Decryptor::new(key);
let dec = Box::new(CbcDecryptor::new(aes_dec, padding, iv.to_vec()));
dec as Box<Decryptor + 'static>
}
}
}
error_chain!{
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links {
Fmt(::std::fmt::Error);
Io(::std::io::Error);
Utf8(::std::str::Utf8Error);
FromUtf8(::std::string::FromUtf8Error);
SerdeJson(::serde_json::Error);
}
}