View Javadoc
1   /*
2    * Copyright 2012-2017 CodeLibs Project and the Others.
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    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.app.web.go;
17  
18  import java.io.IOException;
19  import java.io.UnsupportedEncodingException;
20  import java.net.URLEncoder;
21  import java.util.Map;
22  
23  import javax.annotation.Resource;
24  import javax.servlet.http.HttpServletRequest;
25  
26  import org.codelibs.core.lang.StringUtil;
27  import org.codelibs.core.net.URLUtil;
28  import org.codelibs.fess.Constants;
29  import org.codelibs.fess.app.web.base.FessSearchAction;
30  import org.codelibs.fess.app.web.error.ErrorAction;
31  import org.codelibs.fess.crawler.util.CharUtil;
32  import org.codelibs.fess.es.log.exentity.ClickLog;
33  import org.codelibs.fess.helper.PathMappingHelper;
34  import org.codelibs.fess.helper.SearchLogHelper;
35  import org.codelibs.fess.helper.ViewHelper;
36  import org.codelibs.fess.util.ComponentUtil;
37  import org.codelibs.fess.util.DocumentUtil;
38  import org.dbflute.util.DfTypeUtil;
39  import org.lastaflute.web.Execute;
40  import org.lastaflute.web.response.ActionResponse;
41  import org.lastaflute.web.response.HtmlResponse;
42  import org.lastaflute.web.response.StreamResponse;
43  import org.lastaflute.web.util.LaRequestUtil;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  public class GoAction extends FessSearchAction {
48  
49      // ===================================================================================
50      //                                                                            Constant
51      //
52      private static final Logger logger = LoggerFactory.getLogger(GoAction.class);
53  
54      @Resource
55      protected PathMappingHelper pathMappingHelper;
56  
57      // ===================================================================================
58      //                                                                           Attribute
59      //
60  
61      // ===================================================================================
62      //                                                                               Hook
63      //                                                                              ======
64  
65      // ===================================================================================
66      //                                                                      Search Execute
67      //                                                                      ==============
68      @Execute
69      public ActionResponse index(final GoForm form) throws IOException {
70          validate(form, messages -> {}, () -> asHtml(virtualHost(path_Error_ErrorJsp)));
71          if (isLoginRequired()) {
72              return redirectToLogin();
73          }
74  
75          Map<String, Object> doc = null;
76          try {
77              doc =
78                      searchService.getDocumentByDocId(form.docId,
79                              new String[] { fessConfig.getIndexFieldUrl(), fessConfig.getIndexFieldConfigId() }, getUserBean()).orElse(null);
80          } catch (final Exception e) {
81              logger.warn("Failed to request: " + form.docId, e);
82          }
83          if (doc == null) {
84              saveError(messages -> messages.addErrorsDocidNotFound(GLOBAL, form.docId));
85              return redirect(ErrorAction.class);
86          }
87          final String url = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
88          if (url == null) {
89              saveError(messages -> messages.addErrorsDocumentNotFound(GLOBAL, form.docId));
90              return redirect(ErrorAction.class);
91          }
92  
93          if (fessConfig.isSearchLog()) {
94              final String userSessionId = userInfoHelper.getUserCode();
95              if (userSessionId != null) {
96                  final SearchLogHelper searchLogHelper = ComponentUtil.getSearchLogHelper();
97                  final ClickLog clickLog = new ClickLog();
98                  clickLog.setUrl(url);
99                  clickLog.setRequestedAt(systemHelper.getCurrentTimeAsLocalDateTime());
100                 clickLog.setQueryRequestedAt(DfTypeUtil.toLocalDateTime(Long.parseLong(form.rt)));
101                 clickLog.setUserSessionId(userSessionId);
102                 clickLog.setDocId(form.docId);
103                 clickLog.setQueryId(form.queryId);
104                 if (form.order != null) {
105                     clickLog.setOrder(form.order);
106                 }
107                 searchLogHelper.addClickLog(clickLog);
108             }
109         }
110 
111         String hash;
112         if (StringUtil.isNotBlank(form.hash)) {
113             final String value = URLUtil.decode(form.hash, Constants.UTF_8);
114             final StringBuilder buf = new StringBuilder(value.length() + 100);
115             for (final char c : value.toCharArray()) {
116                 if (CharUtil.isUrlChar(c) || c == ' ') {
117                     buf.append(c);
118                 } else {
119                     try {
120                         buf.append(URLEncoder.encode(String.valueOf(c), Constants.UTF_8));
121                     } catch (final UnsupportedEncodingException e) {
122                         // NOP
123                     }
124                 }
125             }
126             hash = buf.toString();
127         } else {
128             hash = StringUtil.EMPTY;
129         }
130 
131         final String targetUrl = pathMappingHelper.replaceUrl(url);
132         if (isFileSystemPath(targetUrl)) {
133             if (fessConfig.isSearchFileProxyEnabled()) {
134                 final ViewHelper viewHelper = ComponentUtil.getViewHelper();
135                 try {
136                     final StreamResponse response = viewHelper.asContentResponse(doc);
137                     if (response.getHttpStatus().orElse(200) == 404) {
138                         logger.debug("Not found: " + targetUrl);
139                         saveError(messages -> messages.addErrorsNotFoundOnFileSystem(GLOBAL, targetUrl));
140                         return redirect(ErrorAction.class);
141                     }
142                     return response;
143                 } catch (final Exception e) {
144                     logger.warn("Failed to load: " + doc, e);
145                     saveError(messages -> messages.addErrorsNotLoadFromServer(GLOBAL, targetUrl));
146                     return redirect(ErrorAction.class);
147                 }
148             } else {
149                 return redirect(targetUrl + hash);
150             }
151         } else {
152             return redirect(targetUrl + hash);
153         }
154     }
155 
156     protected ActionResponse redirect(final String url) {
157         final HttpServletRequest request2 = LaRequestUtil.getRequest();
158         final String enc = request2.getCharacterEncoding() == null ? Constants.UTF_8 : request2.getCharacterEncoding();
159         final StringBuilder buf = new StringBuilder(url.length() + 100);
160         for (final char c : url.toCharArray()) {
161             if (CharUtil.isUrlChar(c)) {
162                 buf.append(c);
163             } else {
164                 try {
165                     buf.append(URLEncoder.encode(String.valueOf(c), enc));
166                 } catch (final UnsupportedEncodingException e) {
167                     buf.append(c);
168                 }
169             }
170         }
171         return HtmlResponse.fromRedirectPathAsIs(buf.toString());
172     }
173 
174     protected boolean isFileSystemPath(final String url) {
175         return url.startsWith("file:") || url.startsWith("smb:") || url.startsWith("ftp:");
176     }
177 }