PageRenderTime 52ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/htmlunit-2.8/src/main/java/com/gargoylesoftware/htmlunit/javascript/ProxyAutoConfig.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 465 lines | 315 code | 37 blank | 113 comment | 62 complexity | f6b6c02561558ebc334182eb6d957a35 MD5 | raw file
  1. /*
  2. * Copyright (c) 2002-2010 Gargoyle Software Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. package com.gargoylesoftware.htmlunit.javascript;
  16. import java.lang.reflect.Method;
  17. import java.net.InetAddress;
  18. import java.net.URL;
  19. import java.text.SimpleDateFormat;
  20. import java.util.Calendar;
  21. import java.util.TimeZone;
  22. import net.sourceforge.htmlunit.corejs.javascript.Context;
  23. import net.sourceforge.htmlunit.corejs.javascript.ContextFactory;
  24. import net.sourceforge.htmlunit.corejs.javascript.FunctionObject;
  25. import net.sourceforge.htmlunit.corejs.javascript.NativeFunction;
  26. import net.sourceforge.htmlunit.corejs.javascript.Scriptable;
  27. import net.sourceforge.htmlunit.corejs.javascript.ScriptableObject;
  28. import net.sourceforge.htmlunit.corejs.javascript.Undefined;
  29. /**
  30. * Provides an implementation of Proxy Auto-Config (PAC).
  31. *
  32. * @see <a href="http://lib.ru/WEBMASTER/proxy-live.txt">PAC file format</a>
  33. *
  34. * @version $Revision: 5301 $
  35. * @author Ahmed Ashour
  36. */
  37. public final class ProxyAutoConfig {
  38. private ProxyAutoConfig() {
  39. }
  40. /**
  41. * Evaluates the <tt>FindProxyForURL</tt> method of the specified content.
  42. * @param content the JavaScript content
  43. * @param url the URL to be retrieved
  44. * @return semicolon-separated result
  45. */
  46. public static String evaluate(final String content, final URL url) {
  47. final Context cx = ContextFactory.getGlobal().enterContext();
  48. try {
  49. final ProxyAutoConfig config = new ProxyAutoConfig();
  50. final Scriptable scope = cx.initStandardObjects();
  51. config.defineMethod("isPlainHostName", scope);
  52. config.defineMethod("dnsDomainIs", scope);
  53. config.defineMethod("localHostOrDomainIs", scope);
  54. config.defineMethod("isResolvable", scope);
  55. config.defineMethod("isInNet", scope);
  56. config.defineMethod("dnsResolve", scope);
  57. config.defineMethod("myIpAddress", scope);
  58. config.defineMethod("dnsDomainLevels", scope);
  59. config.defineMethod("shExpMatch", scope);
  60. config.defineMethod("weekdayRange", scope);
  61. config.defineMethod("dateRange", scope);
  62. config.defineMethod("timeRange", scope);
  63. cx.evaluateString(scope, "var ProxyConfig = function() {}; ProxyConfig.bindings = {}", "<init>", 1, null);
  64. cx.evaluateString(scope, content, "<Proxy Auto-Config>", 1, null);
  65. final Object functionArgs[] = {url.toExternalForm(), url.getHost()};
  66. final Object fObj = scope.get("FindProxyForURL", scope);
  67. final NativeFunction f = (NativeFunction) fObj;
  68. final Object result = f.call(cx, scope, scope, functionArgs);
  69. return Context.toString(result);
  70. }
  71. finally {
  72. Context.exit();
  73. }
  74. }
  75. private void defineMethod(final String methodName, final Scriptable scope) {
  76. for (Method method : getClass().getMethods()) {
  77. if (method.getName().equals(methodName)) {
  78. final FunctionObject functionObject = new FunctionObject(methodName, method, scope);
  79. ((ScriptableObject) scope).defineProperty(methodName, functionObject, ScriptableObject.EMPTY);
  80. }
  81. }
  82. }
  83. /**
  84. * Returns true if there is no domain name in the hostname (no dots).
  85. * @param host the hostname from the URL (excluding port number).
  86. * @return true if there is no domain name in the hostname (no dots).
  87. */
  88. public static boolean isPlainHostName(final String host) {
  89. return host.indexOf('.') == -1;
  90. }
  91. /**
  92. * Returns true if the domain of hostname matches.
  93. * @param host the hostname from the URL
  94. * @param domain the domain name to test the hostname against
  95. * @return true if the domain of hostname matches.
  96. */
  97. public static boolean dnsDomainIs(final String host, final String domain) {
  98. return host.endsWith(domain);
  99. }
  100. /**
  101. * Returns true if the hostname matches exactly the specified hostname,
  102. * or if there is no domain name part in the hostname, but the unqualified hostname matches.
  103. * @param host the hostname from the URL
  104. * @param hostdom fully qualified hostname to match against
  105. * @return true if the hostname matches exactly the specified hostname,
  106. * or if there is no domain name part in the hostname, but the unqualified hostname matches.
  107. */
  108. public static boolean localHostOrDomainIs(final String host, final String hostdom) {
  109. return host.length() > 1 && host.equals(hostdom) || host.indexOf('.') == -1 && hostdom.startsWith(host);
  110. }
  111. /**
  112. * Tries to resolve the hostname. Returns true if succeeds.
  113. * @param host the hostname from the URL.
  114. * @return true if the specific hostname is resolvable.
  115. */
  116. public static boolean isResolvable(final String host) {
  117. return dnsResolve(host) != null;
  118. }
  119. /**
  120. * Returns true if the IP address of the host matches the specified IP address pattern.
  121. * @param host a DNS hostname, or IP address.
  122. * If a hostname is passed, it will be resolved into an IP address by this function.
  123. * @param pattern an IP address pattern in the dot-separated format
  124. * @param mask mask for the IP address pattern informing which parts of the IP address should be matched against.
  125. * 0 means ignore, 255 means match
  126. * @return true if the IP address of the host matches the specified IP address pattern.
  127. */
  128. public static boolean isInNet(final String host, final String pattern, final String mask) {
  129. final String[] hostTokens = dnsResolve(host).split("\\.");
  130. final String[] patternTokens = pattern.split("\\.");
  131. final String[] maskTokens = mask.split("\\.");
  132. for (int i = 0; i < hostTokens.length; i++) {
  133. if (Integer.parseInt(maskTokens[i]) != 0 && !hostTokens[i].equals(patternTokens[i])) {
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. /**
  140. * Resolves the given DNS hostname into an IP address, and returns it in the dot separated format as a string.
  141. * @param host the hostname to resolve
  142. * @return the resolved IP address
  143. */
  144. public static String dnsResolve(final String host) {
  145. try {
  146. return InetAddress.getByName(host).getHostAddress();
  147. }
  148. catch (final Exception e) {
  149. return null;
  150. }
  151. }
  152. /**
  153. * Returns the IP address of the local host, as a string in the dot-separated integer format.
  154. * @return the IP address of the local host, as a string in the dot-separated integer format.
  155. */
  156. public static String myIpAddress() {
  157. try {
  158. return InetAddress.getLocalHost().getHostAddress();
  159. }
  160. catch (final Exception e) {
  161. throw Context.throwAsScriptRuntimeEx(e);
  162. }
  163. }
  164. /**
  165. * Returns the number (integer) of DNS domain levels (number of dots) in the hostname.
  166. * @param host the hostname from the URL
  167. * @return the number (integer) of DNS domain levels (number of dots) in the hostname.
  168. */
  169. public static int dnsDomainLevels(final String host) {
  170. int levels = 0;
  171. for (int i = host.length() - 1; i >= 0; i--) {
  172. if (host.charAt(i) == '.') {
  173. levels++;
  174. }
  175. }
  176. return levels;
  177. }
  178. /**
  179. * Matches the specified string against a shell expression, not regular expression.
  180. * @param str a string to match
  181. * @param shexp the shell expression
  182. * @return if the string matches
  183. */
  184. public static boolean shExpMatch(final String str, final String shexp) {
  185. final String regexp = shexp.replace(".", "\\.").replace("*", ".*").replace("?", ".");
  186. return str.matches(regexp);
  187. }
  188. /**
  189. * Checks if today is included in the specified range.
  190. * @param wd1 week day 1
  191. * @param wd2 week day 2, optional
  192. * @param gmt string of "GMT", or not specified
  193. * @return if today is in range
  194. */
  195. public static boolean weekdayRange(final String wd1, Object wd2, final Object gmt) {
  196. TimeZone timezone = TimeZone.getDefault();
  197. if ("GMT".equals(Context.toString(gmt)) || "GMT".equals(Context.toString(wd2))) {
  198. timezone = TimeZone.getTimeZone("GMT");
  199. }
  200. if (wd2 == Undefined.instance || "GMT".equals(Context.toString(wd2))) {
  201. wd2 = wd1;
  202. }
  203. final Calendar calendar = Calendar.getInstance(timezone);
  204. for (int i = 0; i < 7; i++) {
  205. final String day = new SimpleDateFormat("EEE").format(calendar.getTime()).toUpperCase();
  206. if (day.equals(wd2)) {
  207. return true;
  208. }
  209. if (day.equals(wd1)) {
  210. return i == 0;
  211. }
  212. calendar.add(Calendar.DAY_OF_WEEK, 1);
  213. }
  214. return false;
  215. }
  216. /**
  217. * Checks if today is included in the specified range.
  218. * @param value1 the value 1
  219. * @param value2 the value 2
  220. * @param value3 the value 3
  221. * @param value4 the value 4
  222. * @param value5 the value 5
  223. * @param value6 the value 6
  224. * @param value7 the value 7
  225. * @return if today is in range
  226. */
  227. public static boolean dateRange(final String value1, final Object value2, final Object value3,
  228. final Object value4, final Object value5, final Object value6, final Object value7) {
  229. final Object[] values = {value1, value2, value3, value4, value5, value6, value7};
  230. TimeZone timezone = TimeZone.getDefault();
  231. //actual values length
  232. int length;
  233. for (length = values.length - 1; length >= 0; length--) {
  234. if (Context.toString(values[length]).equals("GMT")) {
  235. timezone = TimeZone.getTimeZone("GMT");
  236. break;
  237. }
  238. else if (values[length] != Undefined.instance) {
  239. length++;
  240. break;
  241. }
  242. }
  243. int day1, day2, month1, month2, year1, year2;
  244. Calendar cal1;
  245. Calendar cal2;
  246. switch (length) {
  247. case 1:
  248. final int day = getSmallInt(value1);
  249. final int month = dateRange_getMonth(value1);
  250. final int year = dateRange_getYear(value1);
  251. cal1 = dateRange_createCalendar(timezone, day, month, year);
  252. cal2 = (Calendar) cal1.clone();
  253. break;
  254. case 2:
  255. day1 = getSmallInt(value1);
  256. month1 = dateRange_getMonth(value1);
  257. year1 = dateRange_getYear(value1);
  258. cal1 = dateRange_createCalendar(timezone, day1, month1, year1);
  259. day2 = getSmallInt(value2);
  260. month2 = dateRange_getMonth(value2);
  261. year2 = dateRange_getYear(value2);
  262. cal2 = dateRange_createCalendar(timezone, day2, month2, year2);
  263. break;
  264. case 4:
  265. day1 = getSmallInt(value1);
  266. if (day1 != -1) {
  267. month1 = dateRange_getMonth(value2);
  268. day2 = getSmallInt(value3);
  269. month2 = dateRange_getMonth(value4);
  270. cal1 = dateRange_createCalendar(timezone, day1, month1, -1);
  271. cal2 = dateRange_createCalendar(timezone, day2, month2, -1);
  272. }
  273. else {
  274. month1 = dateRange_getMonth(value1);
  275. year1 = dateRange_getMonth(value2);
  276. month2 = getSmallInt(value3);
  277. year2 = dateRange_getMonth(value4);
  278. cal1 = dateRange_createCalendar(timezone, -1, month1, year1);
  279. cal2 = dateRange_createCalendar(timezone, -1, month2, year2);
  280. }
  281. break;
  282. default:
  283. day1 = getSmallInt(value1);
  284. month1 = dateRange_getMonth(value2);
  285. year1 = dateRange_getYear(value3);
  286. day2 = getSmallInt(value4);
  287. month2 = dateRange_getMonth(value5);
  288. year2 = dateRange_getYear(value6);
  289. cal1 = dateRange_createCalendar(timezone, day1, month1, year1);
  290. cal2 = dateRange_createCalendar(timezone, day2, month2, year2);
  291. }
  292. final Calendar today = Calendar.getInstance(timezone);
  293. today.set(Calendar.MILLISECOND, 0);
  294. today.set(Calendar.SECOND, 0);
  295. cal1.set(Calendar.MILLISECOND, 0);
  296. cal1.set(Calendar.SECOND, 0);
  297. cal2.set(Calendar.MILLISECOND, 0);
  298. cal2.set(Calendar.SECOND, 0);
  299. return today.equals(cal1) || (today.after(cal1) && today.before(cal2)) || today.equals(cal2);
  300. }
  301. private static Calendar dateRange_createCalendar(final TimeZone timezone,
  302. final int day, final int month, final int year) {
  303. final Calendar calendar = Calendar.getInstance(timezone);
  304. if (day != -1) {
  305. calendar.set(Calendar.DAY_OF_MONTH, day);
  306. }
  307. if (month != -1) {
  308. calendar.set(Calendar.MONTH, month);
  309. }
  310. if (year != -1) {
  311. calendar.set(Calendar.YEAR, year);
  312. }
  313. return calendar;
  314. }
  315. private static int getSmallInt(final Object object) {
  316. final String s = Context.toString(object);
  317. if (Character.isDigit(s.charAt(0))) {
  318. final int i = Integer.parseInt(s);
  319. if (i < 70) {
  320. return i;
  321. }
  322. }
  323. return -1;
  324. }
  325. private static int dateRange_getMonth(final Object object) {
  326. final String s = Context.toString(object);
  327. if (Character.isLetter(s.charAt(0))) {
  328. try {
  329. final Calendar cal = Calendar.getInstance();
  330. cal.clear();
  331. cal.setTime(new SimpleDateFormat("MMM").parse(s));
  332. return cal.get(Calendar.MONTH);
  333. }
  334. catch (final Exception e) {
  335. //empty
  336. }
  337. }
  338. return -1;
  339. }
  340. private static int dateRange_getYear(final Object object) {
  341. final String s = Context.toString(object);
  342. if (Character.isDigit(s.charAt(0))) {
  343. final int i = Integer.parseInt(s);
  344. if (i > 1000) {
  345. return i;
  346. }
  347. }
  348. return -1;
  349. }
  350. /**
  351. * Checks if the time now is included in the specified range.
  352. * @param value1 the value 1
  353. * @param value2 the value 2
  354. * @param value3 the value 3
  355. * @param value4 the value 4
  356. * @param value5 the value 5
  357. * @param value6 the value 6
  358. * @param value7 the value 7
  359. * @return if the time now is in the range
  360. */
  361. public static boolean timeRange(final String value1, final Object value2, final Object value3,
  362. final Object value4, final Object value5, final Object value6, final Object value7) {
  363. final Object[] values = {value1, value2, value3, value4, value5, value6, value7};
  364. TimeZone timezone = TimeZone.getDefault();
  365. //actual values length
  366. int length;
  367. for (length = values.length - 1; length >= 0; length--) {
  368. if (Context.toString(values[length]).equals("GMT")) {
  369. timezone = TimeZone.getTimeZone("GMT");
  370. break;
  371. }
  372. else if (values[length] != Undefined.instance) {
  373. length++;
  374. break;
  375. }
  376. }
  377. int hour1, hour2, min1, min2, second1, second2;
  378. Calendar cal1;
  379. Calendar cal2;
  380. switch (length) {
  381. case 1:
  382. hour1 = getSmallInt(value1);
  383. cal1 = timeRange_createCalendar(timezone, hour1, -1, -1);
  384. cal2 = (Calendar) cal1.clone();
  385. cal2.add(Calendar.HOUR_OF_DAY, 1);
  386. break;
  387. case 2:
  388. hour1 = getSmallInt(value1);
  389. cal1 = timeRange_createCalendar(timezone, hour1, -1, -1);
  390. hour2 = getSmallInt(value2);
  391. cal2 = timeRange_createCalendar(timezone, hour2, -1, -1);
  392. break;
  393. case 4:
  394. hour1 = getSmallInt(value1);
  395. min1 = getSmallInt(value2);
  396. hour2 = getSmallInt(value3);
  397. min2 = getSmallInt(value4);
  398. cal1 = dateRange_createCalendar(timezone, hour1, min1, -1);
  399. cal2 = dateRange_createCalendar(timezone, hour2, min2, -1);
  400. break;
  401. default:
  402. hour1 = getSmallInt(value1);
  403. min1 = getSmallInt(value2);
  404. second1 = getSmallInt(value3);
  405. hour2 = getSmallInt(value4);
  406. min2 = getSmallInt(value5);
  407. second2 = getSmallInt(value6);
  408. cal1 = dateRange_createCalendar(timezone, hour1, min1, second1);
  409. cal2 = dateRange_createCalendar(timezone, hour2, min2, second2);
  410. }
  411. final Calendar now = Calendar.getInstance(timezone);
  412. return now.equals(cal1) || now.after(cal1) && now.before(cal2) || now.equals(cal2);
  413. }
  414. private static Calendar timeRange_createCalendar(final TimeZone timezone,
  415. final int hour, final int minute, final int second) {
  416. final Calendar calendar = Calendar.getInstance(timezone);
  417. if (hour != -1) {
  418. calendar.set(Calendar.HOUR_OF_DAY, hour);
  419. }
  420. if (minute != -1) {
  421. calendar.set(Calendar.MINUTE, minute);
  422. }
  423. if (second != -1) {
  424. calendar.set(Calendar.SECOND, second);
  425. }
  426. return calendar;
  427. }
  428. }