2022-09-11 00:19:41 +00:00
# include <iostream>
# include <fstream>
# include <filesystem>
2022-09-29 00:56:10 +00:00
# include "episode.h"
2022-09-29 00:02:10 +00:00
# ifdef DROPOUT_DL_SQLITE
2022-09-11 17:21:24 +00:00
# include <sqlite3.h>
2022-09-29 00:02:10 +00:00
# ifdef DROPOUT_DL_GCRYPT
# include <gcrypt.h>
# endif
# endif
2022-09-11 00:19:41 +00:00
2022-09-29 00:02:10 +00:00
static int sqlite_write_callback ( void * data , int argc , char * * argv , char * * azColName )
2022-09-11 17:21:24 +00:00
{
if ( argc < 1 ) {
std : : cerr < < " ERROR: sqlite could not find dropout.tv cookie " < < std : : endl ;
return - 1 ;
}
else {
2022-09-29 00:02:10 +00:00
* ( std : : string * ) data = argv [ 0 ] ;
2022-09-11 17:21:24 +00:00
return 0 ;
}
}
2022-09-29 00:02:10 +00:00
# ifdef DROPOUT_DL_SQLITE
2022-09-29 01:02:56 +00:00
std : : vector < std : : string > get_cookies_from_firefox ( const std : : filesystem : : path & firefox_profile_path , bool verbose = false ) {
2022-09-11 17:21:24 +00:00
2022-09-29 01:02:56 +00:00
std : : fstream firefox_profile_file ( firefox_profile_path ) ;
2022-09-29 00:02:10 +00:00
std : : string firefox_profile ;
2022-09-11 00:19:41 +00:00
2022-09-29 00:02:10 +00:00
std : : string auth_cookie ;
std : : string session_cookie ;
2022-09-11 00:19:41 +00:00
2022-09-29 00:02:10 +00:00
std : : vector < std : : string > out ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
firefox_profile_file > > firefox_profile ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
if ( std : : filesystem : : is_directory ( firefox_profile ) ) {
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
sqlite3 * db ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
if ( verbose ) {
std : : cout < < " Getting firefox cookies from firefox sqlite db \n " ;
}
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
if ( ! std : : filesystem : : is_directory ( " tmp " ) )
std : : filesystem : : create_directories ( " tmp " ) ;
std : : filesystem : : remove ( " tmp/firefox_cookies.sqlite " ) ;
std : : filesystem : : copy_file ( firefox_profile + " /cookies.sqlite " , " tmp/firefox_cookies.sqlite " ) ;
int rc = sqlite3_open ( " tmp/firefox_cookies.sqlite " , & db ) ;
if ( rc ) {
std : : cerr < < " Can't open database: " < < sqlite3_errmsg ( db ) < < ' \n ' ;
exit ( 1 ) ;
} else {
if ( verbose ) {
std : : cout < < " Firefox database opened successfully \n " ;
}
}
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
char * err_code = nullptr ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
std : : string sql ( " SELECT value FROM moz_cookies WHERE host LIKE '%dropout.tv%' AND name='__cf_bm'; " ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
rc = sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & auth_cookie , & err_code ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
out . emplace_back ( auth_cookie ) ;
2022-09-14 01:01:55 +00:00
2022-09-29 00:02:10 +00:00
if ( rc ! = SQLITE_OK ) {
fprintf ( stderr , " SQL error: %s \n " , err_code ) ;
sqlite3_free ( err_code ) ;
sqlite3_close ( db ) ;
exit ( 2 ) ;
} else if ( verbose ) {
std : : cout < < " Got __cf_bm cookie from firefox sqlite db \n " ;
}
sql = " SELECT value FROM moz_cookies WHERE host LIKE '%dropout.tv%' AND name='_session'; " ;
rc = sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & session_cookie , & err_code ) ;
out . emplace_back ( session_cookie ) ;
if ( rc ! = SQLITE_OK ) {
fprintf ( stderr , " SQL error: %s \n " , err_code ) ;
sqlite3_free ( err_code ) ;
sqlite3_close ( db ) ;
exit ( 3 ) ;
} else if ( verbose ) {
std : : cout < < " Got _session cookie from firefox sqlite db \n " ;
}
sqlite3_close ( db ) ;
}
return out ;
}
# ifdef DROPOUT_DL_GCRYPT
2022-09-29 01:02:56 +00:00
std : : vector < std : : string > get_cookies_from_chrome ( const std : : filesystem : : path & chrome_profile_path , bool verbose = false ) {
2022-09-29 00:02:10 +00:00
2022-09-29 01:02:56 +00:00
std : : fstream chrome_profile_file ( chrome_profile_path ) ;
2022-09-29 00:02:10 +00:00
std : : string chrome_profile ;
std : : string auth_cookie ;
int auth_cookie_length ;
std : : string session_cookie ;
int session_cookie_length ;
std : : vector < std : : string > out ;
getline ( chrome_profile_file , chrome_profile ) ;
if ( std : : filesystem : : is_directory ( chrome_profile ) ) {
sqlite3 * db ;
if ( verbose ) {
std : : cout < < " Getting chrome cookies from chrome sqlite db \n " ;
}
int rc = sqlite3_open ( ( chrome_profile + " /Cookies " ) . c_str ( ) , & db ) ;
if ( rc ) {
std : : cerr < < " Can't open database: " < < sqlite3_errmsg ( db ) < < ' \n ' ;
exit ( 1 ) ;
} else {
2022-09-14 01:01:55 +00:00
if ( verbose ) {
2022-09-29 00:02:10 +00:00
std : : cout < < " Chrome database opened successfully \n " ;
2022-09-14 01:01:55 +00:00
}
2022-09-29 00:02:10 +00:00
}
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
char * err_code = nullptr ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
std : : string len ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
std : : string sql = " SELECT length(encrypted_value) FROM cookies WHERE host_key LIKE '%dropout.tv%' AND name='__cf_bm'; " ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & len , & err_code ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
auth_cookie_length = std : : stoi ( len ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
sql = " SELECT encrypted_value FROM cookies WHERE host_key LIKE '%dropout.tv%' AND name='__cf_bm'; " ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
rc = sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & auth_cookie , & err_code ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
if ( rc ! = SQLITE_OK ) {
fprintf ( stderr , " SQL error: %s \n " , err_code ) ;
sqlite3_free ( err_code ) ;
2022-09-11 17:21:24 +00:00
sqlite3_close ( db ) ;
2022-09-29 00:02:10 +00:00
exit ( 2 ) ;
} else if ( verbose ) {
std : : cout < < " Got __cf_bm cookie from chrome sqlite db \n " < < auth_cookie < < ' \n ' ;
}
2022-09-11 17:21:24 +00:00
2022-09-29 00:02:10 +00:00
sql = " SELECT length(encrypted_value) FROM cookies WHERE host_key LIKE '%dropout.tv%' AND name='_session'; " ;
sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & len , & err_code ) ;
session_cookie_length = std : : stoi ( len ) ;
sql = " SELECT encrypted_value FROM cookies WHERE host_key LIKE '%dropout.tv%' AND name='_session'; " ;
rc = sqlite3_exec ( db , sql . c_str ( ) , sqlite_write_callback , & session_cookie , & err_code ) ;
if ( rc ! = SQLITE_OK ) {
fprintf ( stderr , " SQL error: %s \n " , err_code ) ;
sqlite3_free ( err_code ) ;
sqlite3_close ( db ) ;
exit ( 3 ) ;
} else if ( verbose ) {
std : : cout < < " Got _session cookie from chrome sqlite db \n " ;
2022-09-11 17:21:24 +00:00
}
2022-09-29 00:02:10 +00:00
sqlite3_close ( db ) ;
// system(("echo \"SELECT value FROM moz_cookies WHERE originAttributes LIKE '%dropout.tv%';\" | sqlite3 " + firefox_profile + "/cookies.sqlite > cookie").c_str());
2022-09-11 17:21:24 +00:00
}
2022-09-29 00:02:10 +00:00
// For mac os this is your keychain password
// For linux leave as "peanuts"
std : : string password = " peanuts " ;
std : : string salt = " saltysalt " ;
int length = 16 ;
int iterations = 1 ;
uint8_t key [ 32 ] ;
char output [ 2048 ] ;
char iv [ 16 ] ;
for ( char & c : iv ) {
c = ' ' ;
2022-09-11 17:21:24 +00:00
}
2022-09-29 00:02:10 +00:00
for ( char & c : output ) {
c = 0 ;
2022-09-11 17:21:24 +00:00
}
2022-09-29 00:02:10 +00:00
for ( int i = 0 ; i < auth_cookie_length ; i + + ) {
std : : cout < < std : : hex < < ( 0xFF & ( int ) auth_cookie [ i ] ) < < ' ' ;
}
std : : cout < < ' \n ' ;
gcry_kdf_derive ( password . c_str ( ) , password . size ( ) , GCRY_KDF_PBKDF2 , GCRY_KDF_ARGON2ID , salt . c_str ( ) , salt . size ( ) , iterations , length , key ) ;
gcry_cipher_hd_t handle ;
gcry_cipher_open ( & handle , GCRY_CIPHER_AES , GCRY_CIPHER_MODE_CBC , 0 ) ;
gcry_cipher_setkey ( handle , ( const void * ) & key , length ) ;
gcry_cipher_setiv ( handle , ( const void * ) & iv , 16 ) ;
unsigned long err = gcry_cipher_decrypt ( handle , ( unsigned char * ) output , 2048 , auth_cookie . c_str ( ) + 3 , auth_cookie_length - 3 ) ;
if ( err ) {
std : : cout < < gcry_strerror ( err ) < < std : : endl ;
exit ( 2 ) ;
}
for ( char & c : output ) {
if ( c = = ' \017 ' ) {
c = 0 ;
2022-09-11 17:21:24 +00:00
}
}
2022-09-29 00:02:10 +00:00
out . emplace_back ( output ) ;
gcry_cipher_setiv ( handle , ( const void * ) & iv , 16 ) ;
gcry_cipher_decrypt ( handle , ( unsigned char * ) output , 2048 , session_cookie . c_str ( ) + 3 , session_cookie_length - 3 ) ;
out . emplace_back ( output ) ;
return out ;
}
# endif
# endif
2022-09-29 01:02:56 +00:00
std : : vector < std : : string > get_cookies_from_files ( const std : : filesystem : : path & auth_cookie_path , const std : : filesystem : : path & session_cookie_path , bool verbose = false ) {
2022-09-29 00:02:10 +00:00
std : : fstream auth_cookie_file ( " auth_cookie " ) ;
std : : fstream session_cookie_file ( " session_cookie " ) ;
std : : string auth_cookie ;
std : : string session_cookie ;
std : : vector < std : : string > out ;
auth_cookie_file > > auth_cookie ;
if ( verbose ) {
std : : cout < < " Got __cf_bm cookie from auth_cookie file db \n " ;
}
out . emplace_back ( auth_cookie ) ;
session_cookie_file > > session_cookie ;
if ( verbose ) {
std : : cout < < " Got _session cookie from auth_cookie file db \n " ;
}
out . emplace_back ( session_cookie ) ;
return out ;
}
std : : vector < std : : string > get_cookies ( bool verbose = false ) {
2022-09-29 01:02:56 +00:00
# ifdef DROPOUT_DL_SQLITE
std : : filesystem : : path firefox_profile ( " firefox_profile " ) ;
# ifdef DROPOUT_DL_GCRYPT
std : : filesystem : : path chrome_profile ( " chrome_profile " ) ;
# endif
# endif
std : : filesystem : : path auth_cookie ( " auth_cookie " ) ;
std : : filesystem : : path session_cookie ( " session_cookie " ) ;
# ifdef DROPOUT_DL_SQLITE
if ( std : : filesystem : : exists ( firefox_profile ) ) {
return get_cookies_from_firefox ( firefox_profile , verbose ) ;
} else
# ifdef DROPOUT_DL_GCRYPT
if ( std : : filesystem : : exists ( chrome_profile ) ) {
return get_cookies_from_chrome ( chrome_profile , verbose ) ;
} else
# endif
# endif
if ( std : : filesystem : : exists ( auth_cookie ) & & std : : filesystem : : exists ( session_cookie ) ) {
return get_cookies_from_files ( auth_cookie , session_cookie , verbose ) ;
2022-09-29 00:02:10 +00:00
}
else {
std : : cerr < < " ERROR: dropout.tv cookies could not be found " < < std : : endl ;
2022-09-29 01:02:56 +00:00
exit ( 7 ) ;
2022-09-29 00:02:10 +00:00
}
}
int main ( int argc , char * * argv ) {
2022-09-29 02:22:20 +00:00
bool verbose = false ;
std : : string quality = " all " ;
2022-09-29 00:02:10 +00:00
std : : string firefox_profile ;
std : : string chrome_profile ;
std : : string episode_url ;
2022-09-29 00:56:10 +00:00
std : : vector < std : : string > cookies ;
2022-09-11 00:19:41 +00:00
std : : string video_data ;
if ( argc > 1 ) {
2022-09-11 17:21:24 +00:00
episode_url = argv [ 1 ] ;
2022-09-14 01:01:55 +00:00
if ( verbose ) {
2022-09-14 01:05:51 +00:00
std : : cout < < " Got episode url: " < < episode_url < < " from program arguments \n " ;
2022-09-14 01:01:55 +00:00
}
2022-09-11 00:19:41 +00:00
}
else {
std : : cout < < " Enter episode url: " ;
std : : cin > > episode_url ;
}
2022-09-29 00:56:10 +00:00
cookies = get_cookies ( verbose ) ;
2022-09-11 00:19:41 +00:00
2022-09-29 00:56:10 +00:00
dropout_dl : : episode ep ( episode_url , cookies , verbose ) ;
2022-09-11 17:21:24 +00:00
2022-09-29 00:56:10 +00:00
if ( ! std : : filesystem : : is_directory ( ep . series ) ) {
std : : filesystem : : create_directories ( ep . series ) ;
2022-09-14 00:58:30 +00:00
if ( verbose ) {
2022-09-29 00:56:10 +00:00
std : : cout < < " Creating series directory " < < ' \n ' ;
2022-09-11 00:19:41 +00:00
}
}
2022-09-29 02:22:20 +00:00
if ( quality = = " all " ) {
for ( const auto & possible_quality : ep . qualities ) {
if ( ! std : : filesystem : : is_directory ( ep . series + " / " + possible_quality ) ) {
std : : filesystem : : create_directories ( ep . series + " / " + possible_quality ) ;
if ( verbose ) {
std : : cout < < " Creating series directory " < < ' \n ' ;
}
}
std : : fstream out ( ep . series + " / " + possible_quality + " / " + ep . filename ,
std : : ios_base : : in | std : : ios_base : : out | std : : ios_base : : trunc ) ;
2022-09-11 00:19:41 +00:00
2022-09-29 02:22:20 +00:00
out < < ep . get_video_data ( possible_quality ) < < std : : endl ;
}
}
else {
std : : fstream out ( ep . series + " / " + ep . filename , std : : ios_base : : in | std : : ios_base : : out | std : : ios_base : : trunc ) ;
out < < ep . get_video_data ( quality ) < < std : : endl ;
}
2022-09-11 00:19:41 +00:00
return 0 ;
}