|
|
|
|
@@ -35,6 +35,8 @@ class UserFlags {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
static getITTR() 35000;
|
|
|
|
|
|
|
|
|
|
static getExpires() 86400 * 7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TYTD.Downloader {
|
|
|
|
|
@@ -72,6 +74,22 @@ class TYTD.Downloader {
|
|
|
|
|
^/
|
|
|
|
|
public DownloadVideo(id,$res)
|
|
|
|
|
{
|
|
|
|
|
const theVideoId = TYTD.GetVideoId(id);
|
|
|
|
|
if(TypeIsString(theVideoId))
|
|
|
|
|
{
|
|
|
|
|
const ent = {
|
|
|
|
|
Id = theVideoId,
|
|
|
|
|
Resolution = res,
|
|
|
|
|
Cancel = false,
|
|
|
|
|
Type = "Video"
|
|
|
|
|
};
|
|
|
|
|
this.BeforeQueued.Invoke(this, ent);
|
|
|
|
|
if(ent.Cancel) {
|
|
|
|
|
this.LOG("Adding video canceled: {theVideoId}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.LOG($"Adding video: {TYTD.GetVideoId(id)}, original val: {id}");
|
|
|
|
|
switch(res)
|
|
|
|
|
{
|
|
|
|
|
@@ -121,6 +139,19 @@ class TYTD.Downloader {
|
|
|
|
|
|
|
|
|
|
if(pid != null)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
const ent = {
|
|
|
|
|
Id = pid,
|
|
|
|
|
Resolution = res,
|
|
|
|
|
Cancel = false,
|
|
|
|
|
Type = "Playlist"
|
|
|
|
|
};
|
|
|
|
|
this.BeforeQueued.Invoke(this, ent);
|
|
|
|
|
if(ent.Cancel) {
|
|
|
|
|
this.LOG("Adding playlist canceled: {pid}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.LOG($"Adding playlist: https://www.youtube.com/playlist?list={pid}");
|
|
|
|
|
this.PlaylistQueue.Push(()=>{
|
|
|
|
|
each(var item : this.QueryPlaylistItems(pid,true))
|
|
|
|
|
@@ -145,6 +176,18 @@ class TYTD.Downloader {
|
|
|
|
|
|
|
|
|
|
if(cid != null)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
const ent = {
|
|
|
|
|
Id = cid,
|
|
|
|
|
Resolution = res,
|
|
|
|
|
Cancel = false,
|
|
|
|
|
Type = "Channel"
|
|
|
|
|
};
|
|
|
|
|
this.BeforeQueued.Invoke(this, ent);
|
|
|
|
|
if(ent.Cancel) {
|
|
|
|
|
this.LOG("Adding channel canceled: {cid}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.LOG($"Adding channel: https://www.youtube.com/channel/{cid}");
|
|
|
|
|
this.PlaylistQueue.Push(()=>{
|
|
|
|
|
each(var item : this.QueryPlaylistItems($"UU{cid.Substring(2)}",false))
|
|
|
|
|
@@ -182,6 +225,7 @@ class TYTD.Downloader {
|
|
|
|
|
var pid = TYTD.GetPlaylistId(url);
|
|
|
|
|
|
|
|
|
|
var cid = TYTD.GetChannelId(url);
|
|
|
|
|
var tmp = TYTD.GetYouTubeTempPlaylist(url);
|
|
|
|
|
|
|
|
|
|
if(vid != null)
|
|
|
|
|
{
|
|
|
|
|
@@ -195,7 +239,13 @@ class TYTD.Downloader {
|
|
|
|
|
{
|
|
|
|
|
this.DownloadChannel(cid,res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if(tmp != null)
|
|
|
|
|
{
|
|
|
|
|
each(var item : tmp)
|
|
|
|
|
{
|
|
|
|
|
this.DownloadItem(item,res);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/^
|
|
|
|
|
Redirect url to info page
|
|
|
|
|
@@ -204,6 +254,8 @@ class TYTD.Downloader {
|
|
|
|
|
{
|
|
|
|
|
var vid = TYTD.GetVideoId(url);
|
|
|
|
|
var pid = TYTD.GetPlaylistId(url);
|
|
|
|
|
var cid = TYTD.GetChannelId(url);
|
|
|
|
|
var tmp = TYTD.GetYouTubeTempPlaylistRedirect(url);
|
|
|
|
|
|
|
|
|
|
if(vid != null)
|
|
|
|
|
{
|
|
|
|
|
@@ -217,6 +269,10 @@ class TYTD.Downloader {
|
|
|
|
|
{
|
|
|
|
|
return $"./channel?id={Net.Http.UrlEncode(cid)}";
|
|
|
|
|
}
|
|
|
|
|
else if(tmp != null)
|
|
|
|
|
{
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
return "./";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -590,6 +646,29 @@ class TYTD.Downloader {
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
public GetPersonalListTempUrl(name)
|
|
|
|
|
{
|
|
|
|
|
this.Muxex.Lock();
|
|
|
|
|
var db = this.OpenDB();
|
|
|
|
|
var items = [];
|
|
|
|
|
|
|
|
|
|
var lists = Sqlite.Exec(db, $"SELECT * FROM personal_list_entries WHERE listName = {Sqlite.Escape(name)};");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
if(TypeIsList(lists))
|
|
|
|
|
{
|
|
|
|
|
var url = $"https://www.youtube.com/watch_videos?video_ids=";
|
|
|
|
|
var first = true;
|
|
|
|
|
each(var item : lists)
|
|
|
|
|
{
|
|
|
|
|
if(!first) url += $",{item.videoId}";
|
|
|
|
|
else url += item.videoId;
|
|
|
|
|
first=false;
|
|
|
|
|
}
|
|
|
|
|
return url;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
/^ ^/
|
|
|
|
|
public GetPersonalListContents(name, offset, count)
|
|
|
|
|
{
|
|
|
|
|
@@ -716,6 +795,8 @@ class TYTD.Downloader {
|
|
|
|
|
|
|
|
|
|
public VideoProgress = new TYTD.Event();
|
|
|
|
|
|
|
|
|
|
public BeforeQueued = new TYTD.Event();
|
|
|
|
|
|
|
|
|
|
public CurrentVideo = {
|
|
|
|
|
Title = "N/A",
|
|
|
|
|
Channel = "N/A",
|
|
|
|
|
@@ -930,6 +1011,7 @@ class TYTD.Downloader {
|
|
|
|
|
while(this.Running)
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
this.FlushExpired();
|
|
|
|
|
var res = this.PlaylistQueue.Pop();
|
|
|
|
|
|
|
|
|
|
if(TypeOf(res) != "Null")
|
|
|
|
|
@@ -937,7 +1019,7 @@ class TYTD.Downloader {
|
|
|
|
|
res();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var currentTime = DateTime.NowEpoch;
|
|
|
|
|
var currentTime = DateTime.NowEpoch ?? 0;
|
|
|
|
|
var bt = this.Config.BellTimer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1057,26 +1139,27 @@ class TYTD.Downloader {
|
|
|
|
|
if(TypeOf(res) != "Null")
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
res.TYTD = this;
|
|
|
|
|
res.Progress = (progress)=>{
|
|
|
|
|
this.CurrentVideoProgress = progress;
|
|
|
|
|
this.VideoProgress.Invoke(this, {
|
|
|
|
|
Video = res.Video,
|
|
|
|
|
progress
|
|
|
|
|
if(TypeIsDefined(res.TYTD = this)){
|
|
|
|
|
res.Progress = (progress)=>{
|
|
|
|
|
this.CurrentVideoProgress = progress;
|
|
|
|
|
this.VideoProgress.Invoke(this, {
|
|
|
|
|
Video = res.Video,
|
|
|
|
|
progress
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.CurrentVideo = res.Video;
|
|
|
|
|
|
|
|
|
|
this.VideoStarted.Invoke(this,{
|
|
|
|
|
Video = res.Video
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.CurrentVideo = res.Video;
|
|
|
|
|
|
|
|
|
|
this.VideoStarted.Invoke(this,{
|
|
|
|
|
Video = res.Video
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.Start();
|
|
|
|
|
res.Start();
|
|
|
|
|
|
|
|
|
|
this.VideoEnded.Invoke(this,{
|
|
|
|
|
Video = res.Video
|
|
|
|
|
});
|
|
|
|
|
this.VideoEnded.Invoke(this,{
|
|
|
|
|
Video = res.Video
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch(ex) {
|
|
|
|
|
try{
|
|
|
|
|
@@ -1297,7 +1380,10 @@ class TYTD.Downloader {
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS plugin_settings (id INTEGER PRIMARY KEY AUTOINCREMENT, extension TEXT, key TEXT, value TEXT, UNIQUE(extension,key) ON CONFLICT REPLACE);");
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS subscriptions (id INTEGER PRIMARY KEY AUTOINCREMENT, channelId TEXT UNIQUE ON CONFLICT REPLACE, bell TEXT);");
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password_hash TEXT, password_salt TEXT, flags INTEGER);");
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, key TEXT UNIQUE);");
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, key TEXT UNIQUE, expires INTEGER);");
|
|
|
|
|
Sqlite.Exec(db,"CREATE TABLE IF NOT EXISTS sso (id INTEGER PRIMARY KEY AUTOINCREMENT, service_name TEXT UNIQUE, service_pretty_name TEXT, sso_app_key TEXT UNIQUE, service_auth_post TEXT, service_auth_redirect TEXT);");
|
|
|
|
|
Sqlite.Exec(db,"ALTER TABLE sessions ADD expires INTEGER;");
|
|
|
|
|
Sqlite.Exec(db,"DELETE FROM sessions WHERE expires IS NULL;");
|
|
|
|
|
var config=Sqlite.Exec(db,"SELECT * FROM plugin_settings WHERE extension = '' AND key = 'settings';");
|
|
|
|
|
if(TypeOf(config) == "List" && config.Length>0)
|
|
|
|
|
{
|
|
|
|
|
@@ -1798,7 +1884,6 @@ class TYTD.Downloader {
|
|
|
|
|
const token = GetSessionToken(ctx);
|
|
|
|
|
if(TypeIsString(token))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
Sqlite.Exec(db, $"DELETE FROM sessions WHERE key = {Sqlite.Escape(token)};");
|
|
|
|
|
@@ -1831,7 +1916,17 @@ class TYTD.Downloader {
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
public FlushExpired()
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
const currentTime = DateTime.NowEpoch ?? 0;
|
|
|
|
|
const sessions = Sqlite.Exec(db, $"DELETE FROM sessions WHERE expires != 0 AND expires < {currentTime};");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public IsLoggedIn(ctx)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
@@ -1852,13 +1947,32 @@ class TYTD.Downloader {
|
|
|
|
|
if(TypeIsString(sessionToken))
|
|
|
|
|
{
|
|
|
|
|
const res = Sqlite.Exec(db, $"SELECT * FROM sessions s INNER JOIN users u ON s.accountId = u.id WHERE key = {Sqlite.Escape(sessionToken)};");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(TypeIsList(res))
|
|
|
|
|
each(var item : res)
|
|
|
|
|
{
|
|
|
|
|
const whenItExpires = ParseLong(item.expires);
|
|
|
|
|
const currentTime = DateTime.NowEpoch ?? 0;
|
|
|
|
|
if(whenItExpires != 0 && currentTime < whenItExpires && (whenItExpires - currentTime) < (UserFlags.Expires-3600))
|
|
|
|
|
{
|
|
|
|
|
const expiry = currentTime + UserFlags.Expires;
|
|
|
|
|
Sqlite.Exec(db, $"UPDATE sessions SET expires = {expiry} WHERE key = {Sqlite.Escape(sessionToken)};");
|
|
|
|
|
|
|
|
|
|
ctx.WithHeader("Set-Cookie",$"Session={sessionToken}; SameSite=Lax; Expires={new DateTime(expiry).ToHttpDate()}; HttpOnly");
|
|
|
|
|
}
|
|
|
|
|
else if(whenItExpires != 0 && currentTime >= whenItExpires)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Sqlite.Exec(db, $"DELETE FROM sessions WHERE key = {Sqlite.Escape(sessionToken)};");
|
|
|
|
|
item.flags = 0;
|
|
|
|
|
}
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
|
|
|
|
|
return ParseLong(item.flags) | 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1867,9 +1981,26 @@ class TYTD.Downloader {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public GetSSO(appname)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
const res = Sqlite.Exec(db, $"SELECT * FROM sso WHERE service_name = {Sqlite.Escape(appname)}");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
if(TypeIsList(res))
|
|
|
|
|
{
|
|
|
|
|
each(var item : res)
|
|
|
|
|
{
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WhoAmI(ctx)
|
|
|
|
|
{
|
|
|
|
|
his.Mutex.Lock();
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
const res=Sqlite.Exec(db, "SELECT COUNT(*) FROM users;");
|
|
|
|
|
var noAccounts=true;
|
|
|
|
|
@@ -1891,6 +2022,20 @@ class TYTD.Downloader {
|
|
|
|
|
if(TypeIsList(res))
|
|
|
|
|
each(var item : res)
|
|
|
|
|
{
|
|
|
|
|
const whenItExpires = ParseLong(item.expires);
|
|
|
|
|
const currentTime = DateTime.NowEpoch ?? 0;
|
|
|
|
|
if(whenItExpires != 0 && currentTime < whenItExpires && (whenItExpires - currentTime) < (UserFlags.Expires-3600))
|
|
|
|
|
{
|
|
|
|
|
const expiry = currentTime + UserFlags.Expires;
|
|
|
|
|
Sqlite.Exec(db, $"UPDATE sessions SET expires = {expiry} WHERE key = {Sqlite.Escape(sessionToken)};");
|
|
|
|
|
|
|
|
|
|
ctx.WithHeader("Set-Cookie",$"Session={sessionToken}; SameSite=Lax; Expires={new DateTime(expiry).ToHttpDate()}");
|
|
|
|
|
}
|
|
|
|
|
else if(whenItExpires != 0 && currentTime >= whenItExpires)
|
|
|
|
|
{
|
|
|
|
|
Sqlite.Exec(db, $"DELETE FROM sessions WHERE key = {Sqlite.Escape(sessionToken)};");
|
|
|
|
|
item.flags = "0";
|
|
|
|
|
}
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
item.flags = ParseLong(item.flags);
|
|
|
|
|
@@ -1905,9 +2050,9 @@ class TYTD.Downloader {
|
|
|
|
|
public Passwd(ctx, oldPassword, newPassword, logout)
|
|
|
|
|
{
|
|
|
|
|
const whoami = this.WhoAmI(ctx);
|
|
|
|
|
if(TypeIsDictionary(user) && TypeIsString(item.password_salt))
|
|
|
|
|
if(whoami.flags != 0 && TypeIsDictionary(whoami) && TypeIsString(whoami.password_salt))
|
|
|
|
|
{
|
|
|
|
|
var salt = Crypto.Base64Decode(item.password_salt);
|
|
|
|
|
var salt = Crypto.Base64Decode(whoami.password_salt);
|
|
|
|
|
var hash = Crypto.PBKDF2(password, salt, UserFlags.ITTR,64,384);
|
|
|
|
|
var hashStr = Crypto.Base64Encode(hash);
|
|
|
|
|
|
|
|
|
|
@@ -1937,17 +2082,45 @@ class TYTD.Downloader {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return { success=false, reason = "Unable to login for some reason, maybe your token expired"};
|
|
|
|
|
}
|
|
|
|
|
public Login(username, password)
|
|
|
|
|
public Auth(username, password)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
const user = Sqlite.Exec(db, $"SELECT * FROM users WHERE username = {Sqlite.Escape(username)};");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
if(TypeIsList(user))
|
|
|
|
|
{
|
|
|
|
|
each(var item : user)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
var salt = Crypto.Base64Decode(item.password_salt);
|
|
|
|
|
var hash = Crypto.PBKDF2(password, salt, UserFlags.ITTR,64,384);
|
|
|
|
|
var hashStr = Crypto.Base64Encode(hash);
|
|
|
|
|
|
|
|
|
|
if(item.password_hash == hashStr)
|
|
|
|
|
{
|
|
|
|
|
return {flags = ParseLong(item.flags)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
public Login(username, password, doesExpire)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
const user = Sqlite.Exec(db, $"SELECT * FROM users WHERE username = {Sqlite.Escape(username)};");
|
|
|
|
|
|
|
|
|
|
if(TypeIsList(user))
|
|
|
|
|
{
|
|
|
|
|
each(var item : user)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
|
|
|
|
|
var salt = Crypto.Base64Decode(item.password_salt);
|
|
|
|
|
var hash = Crypto.PBKDF2(password, salt, UserFlags.ITTR,64,384);
|
|
|
|
|
@@ -1956,18 +2129,22 @@ class TYTD.Downloader {
|
|
|
|
|
if(item.password_hash == hashStr)
|
|
|
|
|
{
|
|
|
|
|
var rand = Net.Http.UrlEncode(Crypto.Base64Encode(Crypto.RandomBytes(32, "TYTD2025")));
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const dbCon = this.OpenDB();
|
|
|
|
|
Sqlite.Exec(dbCon, $"INSERT INTO sessions (accountId,key) VALUES ({item.id},{Sqlite.Escape(rand)});");
|
|
|
|
|
Sqlite.Close(dbCon);
|
|
|
|
|
|
|
|
|
|
const expires = doesExpire ? ((DateTime.NowEpoch??0) + UserFlags.Expires) : 0;
|
|
|
|
|
Sqlite.Exec(db, $"INSERT INTO sessions (accountId,key,expires) VALUES ({item.id},{Sqlite.Escape(rand)},{expires});");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
return rand;
|
|
|
|
|
}
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
@@ -1992,6 +2169,25 @@ class TYTD.Downloader {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public RegisterSSO(req)
|
|
|
|
|
{
|
|
|
|
|
this.Mutex.Lock();
|
|
|
|
|
const db = this.OpenDB();
|
|
|
|
|
/*
|
|
|
|
|
service_name TEXT UNIQUE, service_pretty_name TEXT, sso_app_key TEXT UNIQUE, service_auth_post TEXT, service_auth_redirect TEXT
|
|
|
|
|
*/
|
|
|
|
|
const resp = Sqlite.Exec(db, $"INSERT INTO sso (service_name, service_pretty_name, sso_app_key, service_auth_post, service_auth_redirect) VALUES ({Sqlite.Escape(req.service_name)},{Sqlite.Escape(req.service_pretty_name)},{Sqlite.Escape(req.sso_app_key)},{Sqlite.Escape(req.service_auth_post)}, {Sqlite.Escape(req.service_auth_redirect)});");
|
|
|
|
|
Sqlite.Close(db);
|
|
|
|
|
this.Mutex.Unlock();
|
|
|
|
|
if(TypeIsList(resp))
|
|
|
|
|
{
|
|
|
|
|
return { success=true};
|
|
|
|
|
}
|
|
|
|
|
else if(TypeIsString(resp))
|
|
|
|
|
{
|
|
|
|
|
return { success = false, reason = resp , type="db"};
|
|
|
|
|
}
|
|
|
|
|
return {success = false, reason = "Unknown", type ="db"};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|