View Javadoc
1   /*
2    * Copyright 2012-2021 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  
25  import org.apache.logging.log4j.LogManager;
26  import org.apache.logging.log4j.Logger;
27  import org.codelibs.core.lang.StringUtil;
28  import org.codelibs.core.net.URLUtil;
29  import org.codelibs.fess.Constants;
30  import org.codelibs.fess.app.web.base.FessSearchAction;
31  import org.codelibs.fess.app.web.error.ErrorAction;
32  import org.codelibs.fess.crawler.util.CharUtil;
33  import org.codelibs.fess.es.log.exentity.ClickLog;
34  import org.codelibs.fess.helper.PathMappingHelper;
35  import org.codelibs.fess.helper.SearchLogHelper;
36  import org.codelibs.fess.helper.ViewHelper;
37  import org.codelibs.fess.util.ComponentUtil;
38  import org.codelibs.fess.util.DocumentUtil;
39  import org.dbflute.util.DfTypeUtil;
40  import org.lastaflute.web.Execute;
41  import org.lastaflute.web.response.ActionResponse;
42  import org.lastaflute.web.response.HtmlResponse;
43  import org.lastaflute.web.response.StreamResponse;
44  
45  public class GoAction extends FessSearchAction {
46  
47      // ===================================================================================
48      //                                                                            Constant
49      //
50      private static final Logger logger = LogManager.getLogger(GoAction.class);
51  
52      @Resource
53      protected PathMappingHelper pathMappingHelper;
54  
55      // ===================================================================================
56      //                                                                           Attribute
57      //
58  
59      // ===================================================================================
60      //                                                                               Hook
61      //                                                                              ======
62  
63      // ===================================================================================
64      //                                                                      Search Execute
65      //                                                                      ==============
66      @Execute
67      public ActionResponse index(final GoForm form) throws IOException {
68          validate(form, messages -> {}, () -> asHtml(virtualHost(path_Error_ErrorJsp)));
69          if (isLoginRequired()) {
70              return redirectToLogin();
71          }
72  
73          Map<String, Object> doc = null;
74          try {
75              doc = searchHelper.getDocumentByDocId(form.docId,
76                      new String[] { fessConfig.getIndexFieldUrl(), fessConfig.getIndexFieldConfigId() }, getUserBean()).orElse(null);
77          } catch (final Exception e) {
78              logger.warn("Failed to request: {}", form.docId, e);
79          }
80          if (doc == null) {
81              saveError(messages -> messages.addErrorsDocidNotFound(GLOBAL, form.docId));
82              return redirect(ErrorAction.class);
83          }
84          final String url = DocumentUtil.getValue(doc, fessConfig.getIndexFieldUrl(), String.class);
85          if (url == null) {
86              saveError(messages -> messages.addErrorsDocumentNotFound(GLOBAL, form.docId));
87              return redirect(ErrorAction.class);
88          }
89  
90          if (fessConfig.isSearchLog()) {
91              final String userSessionId = userInfoHelper.getUserCode();
92              if (userSessionId != null) {
93                  final SearchLogHelper searchLogHelper = ComponentUtil.getSearchLogHelper();
94                  final ClickLog clickLog = new ClickLog();
95                  clickLog.setUrlId((String) doc.get(fessConfig.getIndexFieldId()));
96                  clickLog.setUrl(url);
97                  clickLog.setRequestedAt(systemHelper.getCurrentTimeAsLocalDateTime());
98                  clickLog.setQueryRequestedAt(DfTypeUtil.toLocalDateTime(Long.parseLong(form.rt)));
99                  clickLog.setUserSessionId(userSessionId);
100                 clickLog.setDocId(form.docId);
101                 clickLog.setQueryId(form.queryId);
102                 if (form.order != null) {
103                     clickLog.setOrder(form.order);
104                 }
105                 searchLogHelper.addClickLog(clickLog);
106             }
107         }
108 
109         String hash;
110         if (StringUtil.isNotBlank(form.hash)) {
111             final String value = URLUtil.decode(form.hash, Constants.UTF_8);
112             final StringBuilder buf = new StringBuilder(value.length() + 100);
113             for (final char c : value.toCharArray()) {
114                 if (CharUtil.isUrlChar(c) || c == ' ') {
115                     buf.append(c);
116                 } else {
117                     try {
118                         buf.append(URLEncoder.encode(String.valueOf(c), Constants.UTF_8));
119                     } catch (final UnsupportedEncodingException e) {
120                         // NOP
121                     }
122                 }
123             }
124             hash = buf.toString();
125         } else {
126             hash = StringUtil.EMPTY;
127         }
128 
129         final String targetUrl = pathMappingHelper.replaceUrl(url);
130         if (!isFileSystemPath(targetUrl)) {
131             return HtmlResponse.fromRedirectPathAsIs(DocumentUtil.encodeUrl(targetUrl + hash));
132         }
133         if (!fessConfig.isSearchFileProxyEnabled()) {
134             return HtmlResponse.fromRedirectPathAsIs(targetUrl + hash);
135         }
136         final ViewHelper viewHelper = ComponentUtil.getViewHelper();
137         try {
138             final StreamResponse response = viewHelper.asContentResponse(doc);
139             if (response.getHttpStatus().orElse(200) == 404) {
140                 logger.debug("Not found: {}", targetUrl);
141                 saveError(messages -> messages.addErrorsNotFoundOnFileSystem(GLOBAL, targetUrl));
142                 return redirect(ErrorAction.class);
143             }
144             return response;
145         } catch (final Exception e) {
146             logger.warn("Failed to load: {}", doc, e);
147             saveError(messages -> messages.addErrorsNotLoadFromServer(GLOBAL, targetUrl));
148             return redirect(ErrorAction.class);
149         }
150     }
151 
152     protected boolean isFileSystemPath(final String url) {
153         return url.startsWith("file:") || url.startsWith("smb:") || url.startsWith("smb1:") || url.startsWith("ftp:")
154                 || url.startsWith("storage:");
155     }
156 }