/
index.groovy
120 lines (93 loc) · 4.77 KB
/
index.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package htmlpublisher.HtmlPublisherTarget.BaseHTMLAction
import htmlpublisher.HtmlPublisher
import htmlpublisher.HtmlPublisherTarget
import hudson.Util
import hudson.model.Descriptor
import java.security.MessageDigest
l = namespace(lib.LayoutTagLib)
st = namespace("jelly:stapler")
def text = new File(my.dir(), my.getHTMLTarget().getWrapperName()).text
def actual = Util.toHexString(MessageDigest.getInstance("SHA-1").digest(text.getBytes("UTF-8")))
def expected = null
def useWrapperFileDirectly = null;
def serveWrapper() {
// don't actually serve the wrapper file, but use it as data source for the tab links only
// this minimized the potential for mischief in the case of legacy archives without checksum
st.contentType(value: "text/html;charset=UTF-8")
def header = HtmlPublisher.class.getResourceAsStream("/htmlpublisher/HtmlPublisher/header.html").text
def footer = HtmlPublisher.class.getResourceAsStream("/htmlpublisher/HtmlPublisher/footer.html").text
raw(header)
def legacyFile = new File(my.dir(), "htmlpublisher-wrapper.html")
def matcher = legacyFile.text =~ /<li id="tab\d+" class="unselected" onclick="updateBody\('tab\d+'\);" value="([^"]+)">([^<]+)<\/li>/
def items = []
def itemsTitle = []
while (matcher.find()) {
items.add(matcher.group(1))
itemsTitle.add(matcher.group(2))
}
def idx = 1
items.each { file ->
li(itemsTitle[idx - 1], id: "tab${idx}", class: "unselected", onclick: "updateBody('tab${idx}')", value: file.trim())
idx++
}
// TODO replace unnecessary JS usage by properly integrating header.html/footer.html in this groovy view
raw("<script type=\"text/javascript\">document.getElementById(\"hudson_link\").innerHTML=\"Back to ${my.backToName}\";</script>")
raw("<script type=\"text/javascript\">document.getElementById(\"hudson_link\").href=\"${rootURL}/${my.backToUrl}\";</script>")
raw("<script type=\"text/javascript\">document.getElementById(\"zip_link\").href=\"*zip*/${my.getHTMLTarget().sanitizedName}.zip\";</script>")
raw(footer)
}
def serveWrapperLegacyDirectly() {
// don't actually serve the wrapper file, but use it as data source for the tab links only
// this minimized the potential for mischief in the case of legacy archives without checksum
st.contentType(value: "text/html;charset=UTF-8")
def legacyFile = new File(my.dir(), "htmlpublisher-wrapper.html")
def scriptPattern = legacyFile.text =~ /(<script type="text\/javascript">document.getElementById\("hudson_link"\).innerHTML="Back to )(.*[<>"\\].*)(";<\/script>)/
if (scriptPattern.find()) {
throw new Descriptor.FormException("Can't use illegal character in the Job Name", "JobName")
}
def tabPattern = legacyFile.text =~ /(<li id="tab\d+" class="unselected" onclick="updateBody\('tab\d+'\);" value=")(.*[<>"\\].*)(">)(.*[<>"\\].*)(<\/li>)/
if (tabPattern.find()) {
throw new Descriptor.FormException("Can't use illegal character in the Report Name", "ReportName")
}
def valuePattern = legacyFile.text =~ /(<li id="tab\d+" class="unselected" onclick="updateBody\('tab\d+'\);" value=")([^<]+)(">)(.*[<>"\\].*)(<\/li>)/
if (valuePattern.find()) {
throw new Descriptor.FormException("Can't use illegal character in the Report Name", "ReportName")
}
def titlePattern = legacyFile.text =~ /(<li id="tab\d+" class="unselected" onclick="updateBody\('tab\d+'\);" value=")(.*[<>"\\].*)(">)([^<]+)(<\/li>)/
if (titlePattern.find()) {
throw new Descriptor.FormException("Can't use illegal character in the Report Name", "ReportName")
}
raw(legacyFile.text)
}
if (my instanceof HtmlPublisherTarget.HTMLBuildAction) {
// this is a build action, so needs to have its checksum checked
expected = my.wrapperChecksum
useWrapperFileDirectly = my.getHTMLTarget().useWrapperFileDirectly
} else if (my instanceof HtmlPublisherTarget.HTMLAction && my.actualBuildAction) {
// this is a project action serving a build-level report
expected = my.actualBuildAction.wrapperChecksum
useWrapperFileDirectly = my.getHTMLTarget().useWrapperFileDirectly
} // else this is a project action serving a project-level report, which is considered safe
if (expected == null) {
// no checksum expected
serveWrapper()
} else {
if (expected == actual) {
// checksum expected and matches
if (useWrapperFileDirectly) {
serveWrapperLegacyDirectly()
} else {
serveWrapper()
}
} else {
l.layout {
l.header(title: "Checksum mismatch")
l.main_panel {
h1(_("Checksum mismatch")) {
l.icon(class: 'icon-error icon-xlg')
}
p(raw(_("msg", actual, expected)))
}
}
}
}