]> git.sur5r.net Git - minitube/blobdiff - src/video.cpp
July is the official cat'n'mouse game month
[minitube] / src / video.cpp
index 67796e75b8bc4d2eddb9e063ef4aa2d09bb1ccab..ce351105601cb33c691b8ee73d281f44092d7fe7 100644 (file)
@@ -28,6 +28,10 @@ namespace The {
 NetworkAccess* http();
 }
 
+namespace {
+    static const QString jsNameChars = "a-zA-Z0-9\\$_";
+}
+
 Video::Video() : m_duration(0),
     m_viewCount(-1),
     definitionCode(0),
@@ -333,7 +337,7 @@ void Video::scrapeWebPage(QByteArray data) {
         QString jsPlayerUrl = jsPlayerRe.cap(1);
         jsPlayerUrl.remove('\\');
         jsPlayerUrl = "http:" + jsPlayerUrl;
-        qWarning() << "jsPlayerUrl" << jsPlayerUrl;
+        // qDebug() << "jsPlayerUrl" << jsPlayerUrl;
         /*
         QRegExp jsPlayerIdRe("-(.+)\\.js");
         jsPlayerIdRe.indexIn(jsPlayerUrl);
@@ -390,19 +394,20 @@ void Video::gotHeadHeaders(QNetworkReply* reply) {
 
 void Video::parseJsPlayer(QByteArray bytes) {
     QString js = QString::fromUtf8(bytes);
-    QRegExp funcNameRe("signature=([a-zA-Z0-9]+)");
+    // qWarning() << "jsPlayer" << js;
+    QRegExp funcNameRe("signature=([" + jsNameChars + "]+)");
     if (funcNameRe.indexIn(js) == -1) {
         qWarning() << "Cannot capture signature function name";
     } else {
         sigFuncName = funcNameRe.cap(1);
         captureFunction(sigFuncName, js);
-        // qDebug() << sigFunctions;
+        // qWarning() << sigFunctions;
     }
     parseFmtUrlMap(fmtUrlMap, true);
 }
 
 void Video::captureFunction(const QString &name, const QString &js) {
-    QRegExp funcRe("function\\s+" + name + "\\s*\\([a-zA-Z0-9,\\s]*\\)\\s*\\{[^\\}]+\\}");
+    QRegExp funcRe("function\\s+" + QRegExp::escape(name) + "\\s*\\([" + jsNameChars + ",\\s]*\\)\\s*\\{[^\\}]+\\}");
     if (funcRe.indexIn(js) == -1) {
         qWarning() << "Cannot capture function" << name;
         return;
@@ -411,7 +416,7 @@ void Video::captureFunction(const QString &name, const QString &js) {
     sigFunctions.insert(name, func);
 
     // capture inner functions
-    QRegExp invokedFuncRe("[\\s=;\\(]([a-zA-Z0-9]+)\\s*\\([a-zA-Z0-9, ]+\\)");
+    QRegExp invokedFuncRe("[\\s=;\\(]([" + jsNameChars + "]+)\\s*\\([" + jsNameChars + ",\\s]+\\)");
     int pos = name.length() + 9;
     while ((pos = invokedFuncRe.indexIn(func, pos)) != -1) {
         QString funcName = invokedFuncRe.cap(1);
@@ -419,11 +424,37 @@ void Video::captureFunction(const QString &name, const QString &js) {
             captureFunction(funcName, js);
         pos += invokedFuncRe.matchedLength();
     }
+
+    // capture referenced objects
+    QRegExp objRe("[\\s=;\\(]([" + jsNameChars + "]+)\\.[" + jsNameChars + "]+");
+    pos = name.length() + 9;
+    while ((pos = objRe.indexIn(func, pos)) != -1) {
+        QString objName = objRe.cap(1);
+        if (!sigObjects.contains(objName))
+            captureObject(objName, js);
+        pos += objRe.matchedLength();
+    }
+}
+
+void Video::captureObject(const QString &name, const QString &js) {
+    QRegExp re("var\\s+" + QRegExp::escape(name) + "\\s*=\\s*\\{.+\\}\\s*;");
+    re.setMinimal(true);
+    if (re.indexIn(js) == -1) {
+        qWarning() << "Cannot capture object" << name;
+        return;
+    }
+    QString obj = re.cap(0);
+    sigObjects.insert(name, obj);
 }
 
 QString Video::decryptSignature(const QString &s) {
     if (sigFuncName.isEmpty()) return QString();
     QScriptEngine engine;
+    foreach (QString f, sigObjects.values()) {
+        QScriptValue value = engine.evaluate(f);
+        if (value.isError())
+            qWarning() << "Error in" << f << value.toString();
+    }
     foreach (QString f, sigFunctions.values()) {
         QScriptValue value = engine.evaluate(f);
         if (value.isError())