package org.lognavigator.controller;
import static org.lognavigator.util.Constants.ACTIONS_TABLE_HEADER;
import static org.lognavigator.util.Constants.BREADCRUMBS_KEY;
import static org.lognavigator.util.Constants.DATE_TABLE_HEADER;
import static org.lognavigator.util.Constants.FILE_TABLE_HEADER;
import static org.lognavigator.util.Constants.SIZE_TABLE_HEADER;
import static org.lognavigator.util.Constants.TABLE_HEADERS_KEY;
import static org.lognavigator.util.Constants.TABLE_LAYOUT_CENTERED;
import static org.lognavigator.util.Constants.TABLE_LAYOUT_CLASS_KEY;
import static org.lognavigator.util.Constants.TABLE_LINES_KEY;
import static org.lognavigator.util.Constants.VIEW_TABLE;
import static org.lognavigator.util.Constants.WARN_MESSAGE_KEY;
import static org.lognavigator.util.Constants.WARN_TITLE_KEY;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.lognavigator.bean.Breadcrumb;
import org.lognavigator.bean.FileInfo;
import org.lognavigator.bean.TableCell;
import org.lognavigator.exception.AuthorizationException;
import org.lognavigator.exception.LogAccessException;
import org.lognavigator.service.ConfigService;
import org.lognavigator.service.LogAccessService;
import org.lognavigator.util.BreadcrumbFactory;
import org.lognavigator.util.FileInfoFactory;
import org.lognavigator.util.TableCellFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ListController {
@Autowired
@Qualifier("facade")
private LogAccessService logAccessService;
@Autowired
ConfigService configService;
@RequestMapping({"/logs/{logAccessConfigId}", "/logs/{logAccessConfigId}/"})
public String redirectToList() {
return "redirect:/logs/{logAccessConfigId}/list";
}
@RequestMapping("/logs/{logAccessConfigId}/list")
public String list(Model model,
HttpServletRequest request,
@PathVariable String logAccessConfigId,
@RequestParam(value="subPath", required=false) String subPath
)
throws LogAccessException, IOException, AuthorizationException {
// Is command forbidden ?
checkForbiddenSubPath(subPath);
// List files contained in requested logAccessConfigId/subPath
Set<FileInfo> fileInfos = logAccessService.listFiles(logAccessConfigId, subPath);
// Construct breadcrumbs
if (subPath != null) {
List<Breadcrumb> breadcrumbs = BreadcrumbFactory.createBreadCrumbs(logAccessConfigId);
BreadcrumbFactory.addSubPath(breadcrumbs, subPath, false);
request.setAttribute(BREADCRUMBS_KEY, breadcrumbs);
}
return renderFileList(model, subPath, fileInfos);
}
/**
* Checks that sub path doesn't contain any forbidden path (for security reasons)
* @param subPath sub path to check
* @throws AuthorizationException if subPath contains a forbidden path
*/
void checkForbiddenSubPath(String subPath) throws AuthorizationException {
// Must we check subPath ?
boolean mustCheckSubPath = (subPath != null && configService.getFileListBlockExternalPaths());
if (!mustCheckSubPath) {
return;
}
// Check if subPath is forbidden
String forbiddenSubPathRegex = "^[A-Za-z]:.*|.*(\\.\\.).*|^/.*";
if (subPath.matches(forbiddenSubPathRegex)) {
throw new AuthorizationException("This sub path is forbidden : " + subPath);
}
}
/**
* Render a file list as a HTML table, using list view
* @param model model attributes
* @param subPath path which is listed
* @param fileInfos file list to render
* @return view name to process rendering
*/
String renderFileList(Model model, String subPath, Set<FileInfo> fileInfos) {
// Add a warning if too many files
if (fileInfos.size() >= configService.getFileListMaxCount()) {
model.addAttribute(WARN_TITLE_KEY, "Too many files");
model.addAttribute(WARN_MESSAGE_KEY, "Only the " + configService.getFileListMaxCount() + " last updated files are displayed.");
}
// Add link to parent folder
if (subPath != null && !subPath.equals("/")) {
FileInfo parentFolderLink = FileInfoFactory.createParentFolderLink(subPath);
fileInfos.add(parentFolderLink);
}
// Prepare the table lines for HTML presentation
List<List<TableCell>> tableLines = new ArrayList<List<TableCell>>(fileInfos.size());
// Construct cells for files and folders
for (FileInfo fileInfo : fileInfos) {
List<TableCell> lineCells = TableCellFactory.createTableCellList(fileInfo);
tableLines.add(lineCells);
}
// Add table cells to model so that view can render file list
model.addAttribute(TABLE_HEADERS_KEY, Arrays.asList(FILE_TABLE_HEADER, SIZE_TABLE_HEADER, DATE_TABLE_HEADER, ACTIONS_TABLE_HEADER));
model.addAttribute(TABLE_LINES_KEY, tableLines);
model.addAttribute(TABLE_LAYOUT_CLASS_KEY, TABLE_LAYOUT_CENTERED);
// Return view to display
return VIEW_TABLE;
}
}