OSDN Git Service

有料動画(リダイレクトが複数回発生する)の考慮漏れ修正.
authoryukihane <yukihane.feather@gmail.com>
Sun, 14 Aug 2011 18:39:12 +0000 (03:39 +0900)
committeryukihane <yukihane.feather@gmail.com>
Sun, 14 Aug 2011 18:39:12 +0000 (03:39 +0900)
src/nicobrowser/NicoHttpClient.java

index e55da39..003616f 100644 (file)
@@ -1,6 +1,7 @@
 /*$Id$*/
 package nicobrowser;
 
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Set;
 import java.util.TreeMap;
@@ -45,6 +46,7 @@ import nicobrowser.search.SearchResult;
 import nicobrowser.util.Result;
 import nicobrowser.util.Util;
 import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.http.HttpEntity;
@@ -62,7 +64,10 @@ import org.apache.http.conn.params.ConnRoutePNames;
 import org.apache.http.cookie.Cookie;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.RedirectLocations;
 import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -549,7 +554,7 @@ public class NicoHttpClient {
      * @throws java.io.IOException ファイル取得失敗. 権限の無いファイルを取得しようとした場合も.
      */
     public VideoInfo getVideoInfo(String videoId) throws IOException {
-        final GetRealVideoIdResult res = getRealVideoId(videoId);
+        final GetRealVideoIdResult res = accessWatchPage(videoId);
         final String realVideoId = res.videoId;
 
         String accessUrl = GET_FLV_INFO + realVideoId;
@@ -627,48 +632,40 @@ public class NicoHttpClient {
     }
 
     /**
-     * watchページへアクセスし, ビデオIDを取得する.
-     * soXXXXなど, 実際のビデオIDと異なる場合がある.
-     * @param videoId 取得したいビデオのビデオID.
-     * @return 実際のビデオID.
-     * @throws IOException
-     */
-    private GetRealVideoIdResult getRealVideoId(String videoId) throws IOException {
-        GetRealVideoIdResult res = accessWatchPage(videoId);
-        final String realId = res.videoId;
-
-        // ステータスコード302など、リダイレクトが必要な場合
-        if (!videoId.equals(realId)) {
-            res = getRealVideoId(realId);
-        }
-        return res;
-    }
-
-    /**
      * WATCHページへアクセスする. getflvを行うためには, 必ず事前にWATCHページへアクセスしておく必要があるため.
-     * @param videoId ビデオID.
-     * @return
-     * @throws IOException
+     * WATCHページ参照時にリダイレクトが発生する(so動画ではスレッドIDのWATCHページにリダイレクトされる)場合には
+     * そちらのページにアクセスし、そのスレッドIDをrealIdとして返します.
+     * @param videoId 取得したいビデオのビデオID.
+     * @return 実際のアクセスに必要なIDと、タイトル. タイトルはいんきゅばす互換用です.
+     * @throws IOException アクセスに失敗した場合. 有料動画などがこれに含まれます.
      */
     private GetRealVideoIdResult accessWatchPage(String videoId) throws IOException {
         String realId = videoId;
         String title;
         String watchUrl = WATCH_PAGE + videoId;
         logger.debug("アクセス: " + watchUrl);
-        http.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
+        final HttpGet get = new HttpGet(watchUrl);
+        final HttpContext context = new BasicHttpContext();
+        final HttpResponse response = http.execute(get, context);
         try {
-            HttpGet get = new HttpGet(watchUrl);
-            HttpResponse response = http.execute(get);
-            try {
-                if (response.containsHeader("Location")) {
-                    realId = response.getFirstHeader("Location").getValue().replace("/watch/", "");
+            final RedirectLocations rl = (RedirectLocations) context.getAttribute(
+                    "http.protocol.redirect-locations");
+            // 通常の動画(sm動画など)はリダイレクトが発生しないためnullになる
+            if (rl != null) {
+                final List<URI> locations = rl.getAll();
+                logger.debug("リダイレクト数: " + locations.size());
+
+                // so動画はスレッドIDのページへリダイレクトされる
+                if (locations.size() == 1) {
+                    realId = locations.get(0).toString().replace(WATCH_PAGE, "");
+                } else if (locations.size() > 1) {
+                    throw new IOException("有料動画と思われるため処理を中断しました: " + ArrayUtils.toString(locations));
                 }
-                title = getTitleInWatchPage(response.getEntity().getContent());
-            } finally {
-                response.getEntity().consumeContent();
             }
+
+            title = getTitleInWatchPage(response.getEntity().getContent());
         } finally {
-            http.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true);
+            response.getEntity().consumeContent();
         }
         return new GetRealVideoIdResult(realId, title);
     }