diff --git a/lib/database/user/cookie.dart b/lib/database/user/cookie.dart new file mode 100644 index 000000000..43c7ce806 --- /dev/null +++ b/lib/database/user/cookie.dart @@ -0,0 +1,92 @@ +// This source code is a part of Project Violet. +// Copyright (C) 2020-2023. violet-team. Licensed under the Apache-2.0 License. + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:flutter/services.dart'; + +class CookiesManager { + String? dbPath; + Database? db; + static CookiesManager? _instance; + + CookiesManager({this.dbPath}); + + static CookiesManager create(String dbPath) { + return CookiesManager(dbPath: dbPath); + } + + @protected + @mustCallSuper + void dispose() async { + print('close: ${dbPath!}'); + if (db != null) db!.close(); + } + + static Future getInstance(String dbPath) async { + if (_instance == null) { + _instance = create(dbPath); + await _instance!.open(); + } + return _instance!; + } + + static Future reloadInstance(String dbPath) async { + _instance = create(dbPath); + } + + Future open() async { + db ??= await openDatabase(dbPath!); + } + + Future checkOpen() async { + if(db != null){ + if (!db!.isOpen) db = await openDatabase(dbPath!); + } else if(db == null){ + db = await openDatabase(dbPath!); + } + } + + Future>> query(String str) async { + List> result = []; + await checkOpen(); + result = await db!.rawQuery(str); + return result; + } + + Future execute(String str) async { + await checkOpen(); + await db!.execute(str); + } + + Future insert(String name, Map wh) async { + int result = -1; + await checkOpen(); + result = await db!.insert(name, wh); + return result; + } + + Future update(String name, Map wh, String where, + List args) async { + await checkOpen(); + await db!.update(name, wh, where: where, whereArgs: args); + } + + Future swap(String name, String key, String what, int key1, int key2, + int s1, int s2) async { + await checkOpen(); + await db!.transaction((txn) async { + await txn.rawUpdate('UPDATE $name SET $what=? WHERE $key=?', [s2, key1]); + await txn.rawUpdate('UPDATE $name SET $what=? WHERE $key=?', [s1, key2]); + }); + } + + Future delete(String name, String where, List args) async { + await checkOpen(); + await db!.delete(name, where: where, whereArgs: args); + } +} diff --git a/lib/pages/settings/settings_page.dart b/lib/pages/settings/settings_page.dart index 04c4cd150..b8c6461cc 100644 --- a/lib/pages/settings/settings_page.dart +++ b/lib/pages/settings/settings_page.dart @@ -61,6 +61,7 @@ import 'package:violet/pages/settings/version_page.dart'; import 'package:violet/pages/splash/splash_page.dart'; import 'package:violet/platform/misc.dart'; import 'package:violet/server/violet.dart'; +import 'package:violet/settings/cookie.dart'; import 'package:violet/settings/path.dart'; import 'package:violet/settings/settings.dart'; import 'package:violet/style/palette.dart'; @@ -2230,8 +2231,16 @@ class _SettingsPageState extends State style: ElevatedButton.styleFrom( backgroundColor: Settings.majorColor, ), - child: const Text('Login From WebPage'), - onPressed: () => Navigator.pop(context, 1), + child: ((){ + if(Platform.isAndroid || Platform.isIOS) return const Text('Login From WebPage'); + if(Platform.isLinux) return const Text('Read cookies from firefox'); + })(), + onPressed: (() { + if(Platform.isAndroid || Platform.isIOS) Navigator.pop(context, 1); + if(Platform.isLinux) { + CookieReader.getCookieFirefoxLinux(); + } + }), ), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/lib/settings/cookie.dart b/lib/settings/cookie.dart new file mode 100644 index 000000000..7996dbac7 --- /dev/null +++ b/lib/settings/cookie.dart @@ -0,0 +1,67 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:violet/component/eh/eh_headers.dart'; +import 'package:violet/database/user/cookie.dart'; +import 'package:violet/log/log.dart'; +import 'package:violet/settings/path.dart'; +import 'package:violet/settings/settings.dart'; + +class CookieReader { + static Future getCookieFirefoxLinux() async { + final find_path = '${(await DefaultPathProvider.getHomeDirectory())}'; + var db_path_list = []; + try{ + var process = await Process.start("find", [ + '${find_path}','-name',"cookies.sqlite",'-type','f' + ]); + + await process.stdout + .transform(utf8.decoder) + .forEach((db_path){ + Logger.info(db_path); + if(db_path.isNotEmpty) db_path_list.add(db_path); + }); + } catch(e,st){ + Logger.error("$e\n" + "$st"); + } + db_path_list = (db_path_list.join('\n').split('\n')).where((String element) => (element.isNotEmpty)).toList(); + + for(final db_path in db_path_list){ + final tmp_db_path = '${(await DefaultPathProvider.getBaseDirectory())}/cookies.db.tmp'; + Logger.info(db_path); + if((await File('${tmp_db_path}').exists())){ + await File('${tmp_db_path}').delete(); + } + final db_path_find_result = await Process.run("cp", [ + '${db_path}','${tmp_db_path}' + ]); + final result = await (await CookiesManager.getInstance(tmp_db_path)) + .query("SELECT * FROM moz_cookies WHERE host LIKE '%e-hentai.org'"); + var cookie_str = ''; + result.forEach((row) { + var name,value; + row.entries.forEach((col) { + switch(col.key){ + case 'name': name = col.value; break; + case 'value': value = col.value; break; + } + }); + cookie_str += '${name}=${value}; '; + }); + await (await MultiPreferences.getInstance()) + .setString('eh_cookies', cookie_str); + var login_result_html = await EHSession.requestRedirect('https://e-hentai.org/favorites.php'); + if(login_result_html != null){ + await (await MultiPreferences.getInstance()) + .setString('eh_cookies', ''); + continue; + } + if((await File('${tmp_db_path}').exists())){ + await File('${tmp_db_path}').delete(); + } + break; + } + } +} \ No newline at end of file