/* * Copyright 2016 gitblit.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gitblit.wicket.pages; import java.io.IOException; import java.text.MessageFormat; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.Model; import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import com.gitblit.Constants; import com.gitblit.models.UserModel; import com.gitblit.servlet.RawServlet; import com.gitblit.utils.BugtraqProcessor; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.CacheControl; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.CacheControl.LastModified; import com.gitblit.wicket.MarkupProcessor; import com.gitblit.wicket.MarkupProcessor.MarkupDocument; import com.gitblit.wicket.WicketUtils; @CacheControl(LastModified.REPOSITORY) public class EditFilePage extends RepositoryPage { public EditFilePage(final PageParameters params) { super(params); final UserModel currentUser = (GitBlitWebSession.get().getUser() != null) ? GitBlitWebSession.get().getUser() : UserModel.ANONYMOUS; final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/"); MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter()); Repository r = getRepository(); RevCommit commit = JGitUtils.getCommit(r, objectId); String [] encodings = getEncodings(); // Read raw markup content and transform it to html String documentPath = path; String markupText = JGitUtils.getStringContent(r, commit.getTree(), path, encodings); // Hunt for document if (StringUtils.isEmpty(markupText)) { String name = StringUtils.stripFileExtension(path); List docExtensions = processor.getAllExtensions(); for (String ext : docExtensions) { String checkName = name + "." + ext; markupText = JGitUtils.getStringContent(r, commit.getTree(), checkName, encodings); if (!StringUtils.isEmpty(markupText)) { // found it documentPath = path; break; } } } if (markupText == null) { markupText = ""; } BugtraqProcessor bugtraq = new BugtraqProcessor(app().settings()); markupText = bugtraq.processText(getRepository(), repositoryName, markupText); Fragment fragment; String displayedCommitId = commit.getId().getName(); if (currentUser.canEdit(getRepositoryModel()) && JGitUtils.isTip(getRepository(), objectId.toString())) { final Model documentContent = new Model(markupText); final Model commitMessage = new Model("Document update"); final Model commitIdAtLoad = new Model(displayedCommitId); fragment = new Fragment("doc", "markupContent", this); Form form = new Form("documentEditor") { private static final long serialVersionUID = 1L; @Override protected void onSubmit() { final Repository repository = getRepository(); final String document = documentContent.getObject(); final String message = commitMessage.getObject(); final String branchName = JGitUtils.getBranch(getRepository(), objectId).getName(); final String authorEmail = StringUtils.isEmpty(currentUser.emailAddress) ? (currentUser.username + "@gitblit") : currentUser.emailAddress; boolean success = false; try { ObjectId docAtLoad = getRepository().resolve(commitIdAtLoad.getObject()); logger.trace("Commiting Edit File page: " + commitIdAtLoad.getObject()); DirCache index = DirCache.newInCore(); DirCacheBuilder builder = index.builder(); byte[] bytes = document.getBytes( Constants.ENCODING ); final DirCacheEntry fileUpdate = new DirCacheEntry(path); fileUpdate.setLength(bytes.length); fileUpdate.setLastModified(System.currentTimeMillis()); fileUpdate.setFileMode(FileMode.REGULAR_FILE); fileUpdate.setObjectId(repository.newObjectInserter().insert( org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes )); builder.add(fileUpdate); Set ignorePaths = new HashSet(); ignorePaths.add(path); for (DirCacheEntry entry : JGitUtils.getTreeEntries(repository, branchName, ignorePaths)) { builder.add(entry); } builder.finish(); final boolean forceCommit = false; success = JGitUtils.commitIndex(repository, branchName, index, docAtLoad, forceCommit, currentUser.getDisplayName(), authorEmail, message); } catch (IOException | ConcurrentRefUpdateException e) { e.printStackTrace(); } if (success == false) { getSession().error(MessageFormat.format(getString("gb.fileNotMergeable"),path)); return; } getSession().info(MessageFormat.format(getString("gb.fileCommitted"),path)); setResponsePage(EditFilePage.class, params); } }; final TextArea docIO = new TextArea("content", documentContent); docIO.setOutputMarkupId(false); form.add(new Label("commitAuthor", String.format("%s <%s>", currentUser.getDisplayName(), currentUser.emailAddress))); form.add(new TextArea("commitMessage", commitMessage)); form.setOutputMarkupId(false); form.add(docIO); addBottomScriptInline("attachDocumentEditor(document.querySelector('textarea#editor'), $('#commitDialog'));"); fragment.add(form); } else { MarkupDocument markupDoc = processor.parse(repositoryName, displayedCommitId, documentPath, markupText); final Model documentContent = new Model(markupDoc.html); fragment = new Fragment("doc", "plainContent", this); fragment.add(new Label("content", documentContent).setEscapeModelStrings(false)); } // document page links fragment.add(new BookmarkablePageLink("blameLink", BlamePage.class, WicketUtils.newPathParameter(repositoryName, objectId, documentPath))); fragment.add(new BookmarkablePageLink("historyLink", HistoryPage.class, WicketUtils.newPathParameter(repositoryName, objectId, documentPath))); String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, documentPath); fragment.add(new ExternalLink("rawLink", rawUrl)); add(fragment); } @Override protected String getPageName() { return getString("gb.editFile"); } @Override protected boolean isCommitPage() { return true; } @Override protected Class getRepoNavPageClass() { return EditFilePage.class; } }