Paul Martin
2016-04-30 a502d96a860456ec5e8c96761db70f7cabb74751
commit | author | age
275496 1 /*
PM 2  * Copyright 2016 gitblit.com.
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, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit.wicket.pages;
17
18
19 import java.io.IOException;
795ce2 20 import java.text.MessageFormat;
275496 21 import java.util.HashSet;
PM 22 import java.util.List;
23 import java.util.Set;
24
25 import org.apache.wicket.PageParameters;
26 import org.apache.wicket.markup.html.basic.Label;
27 import org.apache.wicket.markup.html.form.Form;
28 import org.apache.wicket.markup.html.form.TextArea;
29 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
30 import org.apache.wicket.markup.html.link.ExternalLink;
31 import org.apache.wicket.markup.html.panel.Fragment;
32 import org.apache.wicket.model.Model;
33 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
34 import org.eclipse.jgit.dircache.DirCache;
35 import org.eclipse.jgit.dircache.DirCacheBuilder;
36 import org.eclipse.jgit.dircache.DirCacheEntry;
37 import org.eclipse.jgit.lib.FileMode;
38 import org.eclipse.jgit.lib.ObjectId;
39 import org.eclipse.jgit.lib.Repository;
40 import org.eclipse.jgit.revwalk.RevCommit;
41
42 import com.gitblit.Constants;
43 import com.gitblit.models.UserModel;
44 import com.gitblit.servlet.RawServlet;
45 import com.gitblit.utils.BugtraqProcessor;
46 import com.gitblit.utils.JGitUtils;
47 import com.gitblit.utils.StringUtils;
48 import com.gitblit.wicket.CacheControl;
49 import com.gitblit.wicket.GitBlitWebSession;
50 import com.gitblit.wicket.CacheControl.LastModified;
51 import com.gitblit.wicket.MarkupProcessor;
52 import com.gitblit.wicket.MarkupProcessor.MarkupDocument;
53 import com.gitblit.wicket.WicketUtils;
54
795ce2 55 @CacheControl(LastModified.REPOSITORY)
275496 56 public class EditFilePage extends RepositoryPage {
PM 57
58     public EditFilePage(final PageParameters params) {
59         super(params);
60
61         final UserModel currentUser = (GitBlitWebSession.get().getUser() != null) ? GitBlitWebSession.get().getUser() : UserModel.ANONYMOUS;
62         
63         final String path = WicketUtils.getPath(params).replace("%2f", "/").replace("%2F", "/");
64         MarkupProcessor processor = new MarkupProcessor(app().settings(), app().xssFilter());
65
66         Repository r = getRepository();
67         RevCommit commit = JGitUtils.getCommit(r, objectId);
68         String [] encodings = getEncodings();
69
70         // Read raw markup content and transform it to html
71         String documentPath = path;
72         String markupText = JGitUtils.getStringContent(r, commit.getTree(), path, encodings);
73
74         // Hunt for document
75         if (StringUtils.isEmpty(markupText)) {
76             String name = StringUtils.stripFileExtension(path);
77
78             List<String> docExtensions = processor.getAllExtensions();
79             for (String ext : docExtensions) {
80                 String checkName = name + "." + ext;
81                 markupText = JGitUtils.getStringContent(r, commit.getTree(), checkName, encodings);
82                 if (!StringUtils.isEmpty(markupText)) {
83                     // found it
84                     documentPath = path;
85                     break;
86                 }
87             }
88         }
89
90         if (markupText == null) {
91             markupText = "";
92         }
93
94         BugtraqProcessor bugtraq = new BugtraqProcessor(app().settings());
95         markupText = bugtraq.processText(getRepository(), repositoryName, markupText);
96
97         Fragment fragment;
98         String displayedCommitId = commit.getId().getName();
99
795ce2 100         if (currentUser.canEdit(getRepositoryModel()) && JGitUtils.isTip(getRepository(), objectId.toString())) {
275496 101             
811cf0 102             final Model<String> documentContent = new Model<String>(markupText);
275496 103             final Model<String> commitMessage = new Model<String>("Document update");
PM 104             final Model<String> commitIdAtLoad = new Model<String>(displayedCommitId);
105             
106             fragment = new Fragment("doc", "markupContent", this);
107             
108             Form<Void> form = new Form<Void>("documentEditor") {
109                 
110                 private static final long serialVersionUID = 1L;
111
112                 @Override
113                 protected void onSubmit() {
114                     final Repository repository = getRepository();
115                     final String document = documentContent.getObject();
116                     final String message = commitMessage.getObject();
117                     
118                     final String branchName = JGitUtils.getBranch(getRepository(), objectId).getName();
119                     final String authorEmail = StringUtils.isEmpty(currentUser.emailAddress) ? (currentUser.username + "@gitblit") : currentUser.emailAddress;
120                     
121                     boolean success = false;
122
123                     try {            
124                         ObjectId docAtLoad = getRepository().resolve(commitIdAtLoad.getObject());
125                         
795ce2 126                         logger.trace("Commiting Edit File page: " + commitIdAtLoad.getObject());
275496 127                         
PM 128                         DirCache index = DirCache.newInCore();
129                         DirCacheBuilder builder = index.builder();
130                         byte[] bytes = document.getBytes( Constants.ENCODING );
131                         
132                         final DirCacheEntry fileUpdate = new DirCacheEntry(path);
133                         fileUpdate.setLength(bytes.length);
134                         fileUpdate.setLastModified(System.currentTimeMillis());
135                         fileUpdate.setFileMode(FileMode.REGULAR_FILE);
136                         fileUpdate.setObjectId(repository.newObjectInserter().insert( org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes ));
137                         builder.add(fileUpdate);
138                         
139                         Set<String> ignorePaths = new HashSet<String>();
140                         ignorePaths.add(path);
141
142                         for (DirCacheEntry entry : JGitUtils.getTreeEntries(repository, branchName, ignorePaths)) {
143                             builder.add(entry);
144                         }
145                         
146                         builder.finish();
147                         
148                         final boolean forceCommit = false;
149                         
150                         success = JGitUtils.commitIndex(repository,  branchName,  index, docAtLoad, forceCommit, currentUser.getDisplayName(), authorEmail, message);
151                         
152                     } catch (IOException | ConcurrentRefUpdateException e) {
153                         e.printStackTrace();
154                     }
155                 
156                     if (success == false) {
795ce2 157                         getSession().error(MessageFormat.format(getString("gb.fileNotMergeable"),path));
275496 158                         return;
PM 159                     }
160                     
795ce2 161                     getSession().info(MessageFormat.format(getString("gb.fileCommitted"),path));
275496 162                     setResponsePage(EditFilePage.class, params);
PM 163                 }
164             };
165
166             final TextArea<String> docIO = new TextArea<String>("content", documentContent);
167             docIO.setOutputMarkupId(false);
168             
169             form.add(new Label("commitAuthor", String.format("%s <%s>", currentUser.getDisplayName(), currentUser.emailAddress)));
170             form.add(new TextArea<String>("commitMessage", commitMessage));
171             
172             
173             form.setOutputMarkupId(false);
174             form.add(docIO);
175             
176             addBottomScriptInline("attachDocumentEditor(document.querySelector('textarea#editor'), $('#commitDialog'));");
177             
178             fragment.add(form);
179             
180         } else {
181             
811cf0 182             MarkupDocument markupDoc = processor.parse(repositoryName, displayedCommitId, documentPath, markupText);
275496 183             final Model<String> documentContent = new Model<String>(markupDoc.html);
PM 184             
185             fragment = new Fragment("doc", "plainContent", this);
186             
187             fragment.add(new Label("content", documentContent).setEscapeModelStrings(false));
188         }
189
190         // document page links
191         fragment.add(new BookmarkablePageLink<Void>("blameLink", BlamePage.class,
192                 WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));
193         fragment.add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
194                 WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));
195         String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, documentPath);
196         fragment.add(new ExternalLink("rawLink", rawUrl));
197
198         add(fragment);
795ce2 199      
275496 200     }
PM 201
202     @Override
203     protected String getPageName() {
795ce2 204         return getString("gb.editFile");
275496 205     }
PM 206
207     @Override
208     protected boolean isCommitPage() {
209         return true;
210     }
211
212     @Override
213     protected Class<? extends BasePage> getRepoNavPageClass() {
795ce2 214         return EditFilePage.class;
275496 215     }
PM 216     
217     
218
219 }