use std::ffi::CStr;
use std::os::raw::c_char;
use crate::client::LicenseClient;
pub type AgLicenseClient = LicenseClient;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_new(
api_key: *const c_char,
plugin_id: *const c_char,
) -> *mut AgLicenseClient {
let api_key = match unsafe { ptr_to_str(api_key) } {
Some(s) => s,
None => return std::ptr::null_mut(),
};
let plugin_id = match unsafe { ptr_to_str(plugin_id) } {
Some(s) => s,
None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(LicenseClient::new(api_key, plugin_id)))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_new_with_url(
api_key: *const c_char,
plugin_id: *const c_char,
api_url: *const c_char,
) -> *mut AgLicenseClient {
let api_key = match unsafe { ptr_to_str(api_key) } {
Some(s) => s,
None => return std::ptr::null_mut(),
};
let plugin_id = match unsafe { ptr_to_str(plugin_id) } {
Some(s) => s,
None => return std::ptr::null_mut(),
};
let api_url = match unsafe { ptr_to_str(api_url) } {
Some(s) => s,
None => return std::ptr::null_mut(),
};
Box::into_raw(Box::new(
LicenseClient::new(api_key, plugin_id).with_api_url(api_url),
))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_validate(
client: *const AgLicenseClient,
license_key: *const c_char,
) -> i32 {
let client = match unsafe { client.as_ref() } {
Some(c) => c,
None => return -1,
};
let key = match unsafe { ptr_to_str(license_key) } {
Some(s) => s,
None => return -1,
};
match client.validate(key) {
Ok(()) => 0,
Err(e) => e.to_code(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_activate(
client: *const AgLicenseClient,
license_key: *const c_char,
email: *const c_char,
) -> i32 {
let client = match unsafe { client.as_ref() } {
Some(c) => c,
None => return -1,
};
let key = match unsafe { ptr_to_str(license_key) } {
Some(s) => s,
None => return -1,
};
let email = match unsafe { ptr_to_str(email) } {
Some(s) => s,
None => return -1,
};
match client.activate(key, email) {
Ok(_) => 0,
Err(e) => e.to_code(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_start_trial(
client: *const AgLicenseClient,
out_days: *mut u32,
) -> i32 {
let client = match unsafe { client.as_ref() } {
Some(c) => c,
None => return -5,
};
match client.start_trial() {
Ok(trial) => {
if !out_days.is_null() {
unsafe { *out_days = trial.days_remaining };
}
0
}
Err(e) => e.to_code(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_fingerprint(buf: *mut c_char, buf_len: usize) -> i32 {
if buf.is_null() || buf_len < 65 {
return -1;
}
let fp = LicenseClient::machine_fingerprint();
let bytes = fp.as_bytes();
unsafe {
std::ptr::copy_nonoverlapping(bytes.as_ptr(), buf as *mut u8, 64);
*buf.add(64) = 0; }
0
}
#[unsafe(no_mangle)]
pub extern "C" fn ag_license_error_string(code: i32) -> *const c_char {
match code {
0 => c"success".as_ptr(),
-1 => c"license key is invalid".as_ptr(),
-2 => c"license has expired".as_ptr(),
-3 => c"license is bound to a different machine".as_ptr(),
-4 => c"network error (no internet and no cached license)".as_ptr(),
-5 => c"trial period has expired".as_ptr(),
-6 => c"activation limit reached for this license".as_ptr(),
_ => c"unknown error".as_ptr(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ag_license_free(client: *mut AgLicenseClient) {
if !client.is_null() {
drop(unsafe { Box::from_raw(client) });
}
}
unsafe fn ptr_to_str<'a>(ptr: *const c_char) -> Option<&'a str> {
if ptr.is_null() {
return None;
}
unsafe { CStr::from_ptr(ptr) }.to_str().ok()
}