Skip to content

Commit 60794ae

Browse files
committed
[YouTube] Add parenthesis matching as way to parse decrypt function
From @Stypox
1 parent 2967d1a commit 60794ae

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeThrottlingDecrypter.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.schabi.newpipe.extractor.exceptions.ParsingException;
44
import org.schabi.newpipe.extractor.utils.JavaScript;
55
import org.schabi.newpipe.extractor.utils.Parser;
6+
import org.schabi.newpipe.extractor.utils.StringUtil;
67

78
import javax.annotation.Nonnull;
89
import java.util.HashMap;
@@ -71,7 +72,20 @@ private String parseDecodeFunctionName(final String playerJsCode)
7172
@Nonnull
7273
private String parseDecodeFunction(final String playerJsCode, final String functionName)
7374
throws Parser.RegexException {
74-
Pattern functionPattern = Pattern.compile(functionName + "=function(.*?};)\n",
75+
try {
76+
return parseWithParenthesisMatching(playerJsCode, functionName);
77+
} catch (Exception e) {
78+
return parseWithRegex(playerJsCode, functionName);
79+
}
80+
}
81+
82+
private String parseWithParenthesisMatching(final String playerJsCode, final String functionName) {
83+
final String functionBase = functionName + "=function";
84+
return functionBase + StringUtil.matchToClosingParenthesis(playerJsCode, functionBase) + ";";
85+
}
86+
87+
private String parseWithRegex(final String playerJsCode, final String functionName) throws Parser.RegexException {
88+
Pattern functionPattern = Pattern.compile(functionName + "=function(.*?}};)\n",
7589
Pattern.DOTALL);
7690
return "function " + functionName + Parser.matchGroup1(functionPattern, playerJsCode);
7791
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.schabi.newpipe.extractor.utils;
2+
3+
import edu.umd.cs.findbugs.annotations.NonNull;
4+
5+
public class StringUtil {
6+
7+
private StringUtil() {
8+
}
9+
10+
/**
11+
* @param string The string to search in
12+
* @param start A string from which to start searching.
13+
* @return A substring where each '{' matches a '}'
14+
* @throws IndexOutOfBoundsException If {@ string} does not contain {@code start}
15+
*/
16+
@NonNull
17+
public static String matchToClosingParenthesis(@NonNull final String string, @NonNull final String start) {
18+
int startIndex = string.indexOf(start);
19+
if (startIndex < 0) {
20+
throw new IndexOutOfBoundsException();
21+
}
22+
23+
startIndex += start.length();
24+
int endIndex = startIndex;
25+
while (string.charAt(endIndex) != '{') {
26+
++endIndex;
27+
}
28+
++endIndex;
29+
30+
int openParenthesis = 1;
31+
while (openParenthesis > 0) {
32+
switch (string.charAt(endIndex)) {
33+
case '{':
34+
++openParenthesis;
35+
break;
36+
case '}':
37+
--openParenthesis;
38+
break;
39+
default:
40+
break;
41+
}
42+
++endIndex;
43+
}
44+
45+
return string.substring(startIndex, endIndex);
46+
}
47+
}

0 commit comments

Comments
 (0)