diff --git a/BiliLocal.pro b/BiliLocal.pro index 9b211deb..c9c7593b 100644 --- a/BiliLocal.pro +++ b/BiliLocal.pro @@ -10,6 +10,12 @@ TEMPLATE = app CONFIG += c++11 +INCLUDEPATH += \ + C:/msys64/usr/local/include + +LIBS += \ + -LC:/msys64/usr/local/lib + SOURCES += \ src/APlayer.cpp \ src/Config.cpp \ diff --git a/res/DATA b/res/DATA index 0468fe61..d03a8c4f 100644 --- a/res/DATA +++ b/res/DATA @@ -62,7 +62,7 @@ "99": "未知" }, "Logo": { - "DirectX": "http://upload.wikimedia.org/wikipedia/commons/1/11/DirectX_logo.png", + "DirectX": "https://upload.wikimedia.org/wikipedia/commons/1/11/DirectX_logo.png", "FFmpeg": "http://www.ffmpeg.org/ffmpeg-logo.png", "OpenGL": "https://www.khronos.org/assets/uploads/ceimg/made/assets/uploads/apis/OpenGL-ES_300_199_75.png", "VLC": "http://images.videolan.org/images/logoOrange.png" diff --git a/src/APlayer.cpp b/src/APlayer.cpp index c788d64f..bfd1a370 100644 --- a/src/APlayer.cpp +++ b/src/APlayer.cpp @@ -26,6 +26,7 @@ #include "APlayer.h" #include "Config.h" +#include "List.h" #include "Local.h" #include "Render.h" #include "Utils.h" @@ -741,13 +742,17 @@ QList QPlayer::getTracks(int) void QPlayer::play() { - QMetaObject::invokeMethod(mp,getState()==Play?"pause":"play",Qt::BlockingQueuedConnection); + if(getState()==Play){ + List::instance()->saveList(); + Config::save(); + } + QMetaObject::invokeMethod(mp,getState()==Play?"pause":"play",Qt::BlockingQueuedConnection); } void QPlayer::stop(bool manually) { manuallyStopped=manually; - QMetaObject::invokeMethod(mp,"stop",Qt::BlockingQueuedConnection); + QMetaObject::invokeMethod(mp,"stop",Qt::BlockingQueuedConnection); } void QPlayer::setTime(qint64 _time) @@ -808,7 +813,7 @@ class NPlayer:public APlayer { public: explicit NPlayer(QObject *parent=0); - QList getTracks(int type); + QList getTracks(int type); private: qint64 start; diff --git a/src/Config.cpp b/src/Config.cpp index f7cc3676..e03d7f76 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -34,6 +34,12 @@ #include "Utils.h" #include +extern "C" +{ +#include +#include +} + Config *Config::ins=nullptr; Config *Config::instance() @@ -1047,7 +1053,7 @@ ConfigDialog::ConfigDialog(QWidget *parent,int index): info->setText(Config::tr("waiting")); l->addWidget(info,0,3); auto loadValid=[=](){ - QString url("https://secure.%1/captcha?r=%2"); + QString url("https://passport.%1/captcha?r=%2"); url=url.arg(Utils::customUrl(Utils::Bilibili)); url=url.arg(qrand()/(double)RAND_MAX); fillPicture(info,url,Config::tr("error"),QSize(200,25)); @@ -1066,42 +1072,95 @@ ConfigDialog::ConfigDialog(QWidget *parent,int index): for(QLineEdit *iter:sheet){ iter->setEnabled(!logged); } - }; - auto sendLogin=[this,setLogged](){ - click->setEnabled(false); - QUrlQuery query; - query.addQueryItem("act","login"); - query.addQueryItem("userid",sheet[0]->text()); - query.addQueryItem("pwd",sheet[1]->text()); - query.addQueryItem("vdcode",sheet[2]->text()); - query.addQueryItem("keeptime","2592000"); - QByteArray data=query.query().toUtf8(); - QString url("https://secure.%1/login"); - url=url.arg(Utils::customUrl(Utils::Bilibili)); - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); - request.setHeader(QNetworkRequest::ContentLengthHeader,data.length()); - QNetworkReply *reply=manager->post(request,data); - connect(reply,&QNetworkReply::finished,[=](){ - bool flag=false; - if(reply->error()==QNetworkReply::NoError){ - QString page(reply->readAll()); - if(page.indexOf("setTimeout('JumpUrl()',2000)")!=-1){ - flag=true; - } - else{ - int sta=page.indexOf("document.write(\"")+16; - QMessageBox::warning(this,Config::tr("Warning"),page.mid(sta,page.indexOf("\"",sta)-sta)); - } - } - click->setEnabled(true); - setLogged(flag); - reply->deleteLater(); - }); + }; + auto sendLogin=[this,setLogged](){ + click->setEnabled(false); + QString url("https://passport.%1/login?act=getkey"); + url=url.arg(Utils::customUrl(Utils::Bilibili)); + QNetworkRequest request(url); + QNetworkReply *reply=manager->get(request); + connect(reply,&QNetworkReply::finished,[=](){ + QString pwd=sheet[1]->text(); + try{ + QJsonObject key = QJsonDocument::fromJson(reply->readAll()).object(); + qDebug() << key; + static QLibrary lib; + static BIO *(*BIO_new_mem_buf)(void *, int); + static RSA *(*PEM_read_bio_RSA_PUBKEY)(BIO *, RSA **, pem_password_cb *, void *); + static int(*RSA_public_encrypt)(int, const unsigned char *, unsigned char *, RSA *, int); + if (lib.fileName().isEmpty()){ + for (const QString &name : { "libeay32", "libcrypto" }){ + lib.setFileName(name); + if (lib.load()){ + BIO_new_mem_buf = (decltype(BIO_new_mem_buf))lib.resolve("BIO_new_mem_buf"); + PEM_read_bio_RSA_PUBKEY = (decltype(PEM_read_bio_RSA_PUBKEY))lib.resolve("PEM_read_bio_RSA_PUBKEY"); + RSA_public_encrypt = (decltype(RSA_public_encrypt))lib.resolve("RSA_public_encrypt"); + break; + } + } + } + if (!lib.isLoaded()){ + throw "failed to load openssl library"; + } + QByteArray pub = key["key"].toString().toUtf8(); + BIO *bio = BIO_new_mem_buf(pub.data(), pub.length()); + if (!bio){ + throw "failed to generate BIO"; + } + RSA *rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + if (!rsa){ + throw "failed to generate RSA_PUBKEY"; + } + pwd.prepend(key["hash"].toString()); + QByteArray dat = pwd.toUtf8(); + QByteArray buf; + buf.resize(1024); + int len = RSA_public_encrypt(dat.length(), (const unsigned char *)dat.data(), (unsigned char*)buf.data(), rsa, RSA_PKCS1_PADDING); + if (len == -1){ + throw "failed to encrypt using RSA"; + } + buf.resize(len); + pwd = buf.toBase64(); + } + catch (...) + { + QMessageBox::warning(this,Config::tr("warning"),"An error occurred in RSA encryption"); + return; + } + + QUrlQuery query; + query.addQueryItem("userid",sheet[0]->text()); + query.addQueryItem("pwd",pwd.replace("+","%2B")); + query.addQueryItem("captcha",sheet[2]->text()); + QByteArray data=query.query().toUtf8(); + QString url("https://passport.%1/ajax/miniLogin/login"); + url=url.arg(Utils::customUrl(Utils::Bilibili)); + QNetworkRequest request(url); + request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); + request.setHeader(QNetworkRequest::ContentLengthHeader,data.length()); + QNetworkReply *reply=manager->post(request,data); + connect(reply,&QNetworkReply::finished,[=](){ + bool flag=false; + if(reply->error()==QNetworkReply::NoError){ + QString page(reply->readAll()); + if(page.indexOf("\"status\":true")!=-1){ + flag=true; + } + else{ + //int sta=page.indexOf("document.write(\"")+16; + //QMessageBox::warning(this,Config::tr("Warning"),page.mid(sta,page.indexOf("\"",sta)-sta)); + QMessageBox::warning(this,Config::tr("Warning"),page); + } + } + click->setEnabled(true); + setLogged(flag); + reply->deleteLater(); + }); + }); }; auto setLogout=[=](){ click->setEnabled(false); - QString url="https://secure.%1/login?act=exit"; + QString url="https://passport.%1/login?act=exit"; url=url.arg(Utils::customUrl(Utils::Bilibili)); QNetworkReply *reply=manager->get(QNetworkRequest(url)); connect(reply,&QNetworkReply::finished,[=](){ @@ -1449,4 +1508,4 @@ void Config::setVariant(QString key,QVariant val) QVariant Config::getVariant(QString key,QVariant val) { return getValue(key,val); -} \ No newline at end of file +} diff --git a/src/List.cpp b/src/List.cpp index 63e77f4e..c98dac9c 100644 --- a/src/List.cpp +++ b/src/List.cpp @@ -279,6 +279,42 @@ List::~List() Config::setValue("/Playing/List",list); } +void List::saveList() +{ + QJsonArray list; + updateCurrent(); + for(int i=0;iitem(i); + QJsonObject data; + data["File"]=item->data(FileRole).toString(); + data["Time"]=item->data(TimeRole).toDouble(); + data["Date"]=item->data(DateRole).toString(); + switch(item->data(CodeRole).toInt()){ + case Records: + { + QJsonArray danm; + for(int i=0;irowCount();++i){ + QStandardItem *c=item->child(i); + QJsonObject d; + d["Code"]=c->data(CodeRole).toString(); + d["Time"]=c->data(TimeRole).toDouble(); + danm.append(d); + } + data["Danm"]=danm; + break; + } + case Inherit: + data["Danm"]="Inherit"; + break; + case Surmise: + data["Danm"]="Surmise"; + break; + } + list.append(data); + } + Config::setValue("/Playing/List",list); +} + QStringList List::mimeTypes() const { return {"application/x-bililocallistdata"}; diff --git a/src/List.h b/src/List.h index e8a538b2..9837e9b9 100644 --- a/src/List.h +++ b/src/List.h @@ -50,6 +50,7 @@ class List:public QStandardItemModel }; ~List(); + void saveList(); static List *instance(); QStringList mimeTypes() const; QMimeData *mimeData(const QModelIndexList &) const; @@ -69,7 +70,7 @@ public slots: QStandardItem *itemFromFile(QString file,bool create=false); bool finished(); void appendMedia(QString file); - void updateCurrent(); + void updateCurrent(); void split(const QModelIndex &index); void split(const QModelIndexList &indexes); void waste(const QModelIndex &index); diff --git a/src/Load.cpp b/src/Load.cpp index 27bf2a18..bc2820dc 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -279,7 +279,7 @@ Load::Load(QObject *parent): model->clear(); QString api,id,video(reply->readAll()); int sta; - if((sta=video.indexOf("
"))!=-1&&sharp==-1){ + if((sta=video.indexOf("
"))!=-1&&sharp==-1){ int len=video.indexOf("",sta)-sta+1; len=len<0?0:len; QString select=video.mid(sta,len); diff --git a/src/Render.cpp b/src/Render.cpp index 3eace663..38b8e77b 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -130,6 +130,7 @@ extern "C" #include #include #include +#define PIX_FMT_HWACCEL 8 } class RasterRenderPrivate:public RenderPrivate diff --git a/src/Utils.cpp b/src/Utils.cpp index df0f4996..e7d54887 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -295,7 +295,7 @@ QString Utils::customUrl(Site site) return QString(); } QStringList urls,defs; - defs<<"acfun.tv"<<"bilibili.com"<<"acplay.net"<<"tucao.cc"; + defs<<"acfun.tv"<<"bilibili.com"<<"acplay.net"<<"tucao.tv"; urls=Config::getValue("/Network/Url",defs.join(';')).split(';',QString::SkipEmptyParts); for (QString iter:urls+defs){ if (iter.toLower().indexOf(name)!=-1){