Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 09deb82

Browse files
committed
Improving the exception page provided by HtmlErrorRenderer
1 parent 7dfc97b commit 09deb82

25 files changed

+1183
-218
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/error_renderer.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
<argument>%kernel.debug%</argument>
1515
<argument>%kernel.charset%</argument>
1616
<argument>%debug.file_link_format%</argument>
17+
<argument>%kernel.project_dir%</argument>
18+
<argument type="service" id="request_stack" />
19+
<argument type="service" id="logger" on-invalid="null" />
1720
</service>
1821

1922
<service id="error_renderer.renderer.json" class="Symfony\Component\ErrorRenderer\ErrorRenderer\JsonErrorRenderer">

src/Symfony/Component/ErrorHandler/Tests/ExceptionHandlerTest.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,15 @@ public function testDebug()
5252
$response = ob_get_clean();
5353

5454
$this->assertContains('<h1 class="break-long-words exception-message">Foo</h1>', $response);
55-
$this->assertContains('<div class="trace trace-as-html">', $response);
55+
$this->assertContains('<div class="trace trace-as-html" id="trace-box-1">', $response);
5656

5757
// taken from https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
58-
$htmlWithXss = '<body onload=alert(\'test1\')> <b onmouseover=alert(\'Wufff!\')>click me!</b> <img src="j&#X41vascript:alert(\'test2\')"> <meta http-equiv="refresh"
59-
content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">';
58+
$htmlWithXss = '<body onload=alert(\'test1\')> <b onmouseover=alert(\'Wufff!\')>click me!</b> <img src="j&#X41vascript:alert(\'test2\')"> <meta http-equiv="refresh" content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">';
6059
ob_start();
6160
$handler->sendPhpResponse(new \RuntimeException($htmlWithXss));
6261
$response = ob_get_clean();
6362

64-
$this->assertContains(sprintf('<h1 class="break-long-words exception-message">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response);
63+
$this->assertContains(sprintf('<h1 class="break-long-words exception-message long">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response);
6564
}
6665

6766
public function testStatusCode()
@@ -106,7 +105,7 @@ public function testNestedExceptions()
106105
$handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
107106
$response = ob_get_clean();
108107

109-
$this->assertStringMatchesFormat('%A<p class="break-long-words trace-message">Foo</p>%A<p class="break-long-words trace-message">Bar</p>%A', $response);
108+
$this->assertStringMatchesFormat('%A<h1 class="break-long-words exception-message">Foo</h1>%A<p class="break-long-words trace-message">Bar</p>%A', $response);
110109
}
111110

112111
public function testHandle()

src/Symfony/Component/ErrorRenderer/ErrorRenderer/HtmlErrorRenderer.php

Lines changed: 199 additions & 212 deletions
Large diffs are not rendered by default.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; }
2+
.container { margin: 30px; max-width: 600px; }
3+
h1 { color: #dc3545; font-size: 24px; }
4+
h2 { font-size: 18px; }
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig.
2+
If you make any change in this file, verify the same change is needed in the other file. */
3+
:root {
4+
--font-sans-serif: Helvetica, Arial, sans-serif;
5+
--page-background: #f9f9f9;
6+
--color-text: #222;
7+
/* when updating any of these colors, do the same in toolbar.css.twig */
8+
--color-success: #4f805d;
9+
--color-warning: #a46a1f;
10+
--color-error: #b0413e;
11+
--color-muted: #999;
12+
--tab-background: #fff;
13+
--tab-color: #444;
14+
--tab-active-background: #666;
15+
--tab-active-color: #fafafa;
16+
--tab-disabled-background: #f5f5f5;
17+
--tab-disabled-color: #999;
18+
--metric-value-background: #fff;
19+
--metric-value-color: inherit;
20+
--metric-unit-color: #999;
21+
--metric-label-background: #e0e0e0;
22+
--metric-label-color: inherit;
23+
--table-border: #e0e0e0;
24+
--table-background: #fff;
25+
--table-header: #e0e0e0;
26+
--trace-selected-background: #F7E5A1;
27+
--tree-active-background: #F7E5A1;
28+
--exception-title-color: var(--base-2);
29+
--shadow: 0px 0px 1px rgba(128, 128, 128, .2);
30+
--border: 1px solid #e0e0e0;
31+
--background-error: var(--color-error);
32+
--highlight-comment: #969896;
33+
--highlight-default: #222222;
34+
--highlight-keyword: #a71d5d;
35+
--highlight-string: #183691;
36+
--base-0: #fff;
37+
--base-1: #f5f5f5;
38+
--base-2: #e0e0e0;
39+
--base-3: #ccc;
40+
--base-4: #666;
41+
--base-5: #444;
42+
--base-6: #222;
43+
}
44+
45+
html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}
46+
47+
html {
48+
/* always display the vertical scrollbar to avoid jumps when toggling contents */
49+
overflow-y: scroll;
50+
}
51+
body { background-color: #F9F9F9; color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; }
52+
53+
a { cursor: pointer; text-decoration: none; }
54+
a:hover { text-decoration: underline; }
55+
abbr[title] { border-bottom: none; cursor: help; text-decoration: none; }
56+
57+
code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; }
58+
59+
table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; }
60+
table { background: #FFF; border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; }
61+
table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; }
62+
table th { background-color: var(--base-2); font-weight: bold; text-align: left; }
63+
64+
.m-t-5 { margin-top: 5px; }
65+
.hidden-xs-down { display: none; }
66+
.block { display: block; }
67+
.full-width { width: 100%; }
68+
.hidden { display: none; }
69+
.prewrap { white-space: pre-wrap; }
70+
.nowrap { white-space: nowrap; }
71+
.newline { display: block; }
72+
.break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; }
73+
.text-small { font-size: 12px !important; }
74+
.text-muted { color: #999; }
75+
.text-bold { font-weight: bold; }
76+
.empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; }
77+
78+
.status-success { background: rgba(94, 151, 110, 0.3); }
79+
.status-warning { background: rgba(240, 181, 24, 0.3); }
80+
.status-error { background: rgba(176, 65, 62, 0.2); }
81+
.status-success td, .status-warning td, .status-error td { background: transparent; }
82+
tr.status-error td, tr.status-warning td { border-bottom: 1px solid #FAFAFA; border-top: 1px solid #FAFAFA; }
83+
.status-warning .colored { color: #A46A1F; }
84+
.status-error .colored { color: var(--color-error); }
85+
86+
.sf-toggle { cursor: pointer; }
87+
.sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; }
88+
.sf-toggle-content.sf-toggle-hidden { display: none; }
89+
.sf-toggle-content.sf-toggle-visible { display: block; }
90+
thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; }
91+
.sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; }
92+
.sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; }
93+
94+
.tab-navigation { margin: 0 0 1em 0; padding: 0; }
95+
.tab-navigation li { background: var(--tab-background); border: 1px solid var(--table-border); color: var(--tab-color); cursor: pointer; display: inline-block; font-size: 16px; margin: 0 0 0 -1px; padding: .5em .75em; z-index: 1; }
96+
.tab-navigation li .badge { background-color: var(--base-1); color: var(--base-4); display: inline-block; font-size: 14px; font-weight: bold; margin-left: 8px; min-width: 10px; padding: 1px 6px; text-align: center; white-space: nowrap; }
97+
.tab-navigation li.disabled { background: var(--tab-disabled-background); color: var(--tab-disabled-color); }
98+
.tab-navigation li.active { background: var(--tab-active-background); color: var(--tab-active-color); z-index: 1100; }
99+
.tab-navigation li.active .badge { background-color: var(--base-5); color: var(--base-2); }
100+
.tab-content > *:first-child { margin-top: 0; }
101+
.tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; }
102+
.tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; }
103+
.sf-tabs .tab:not(:first-child) { display: none; }
104+
105+
[data-filters] { position: relative; }
106+
[data-filtered] { cursor: pointer; }
107+
[data-filtered]:after { content: '\00a0\25BE'; }
108+
[data-filtered]:hover .filter-list li { display: inline-flex; }
109+
[class*="filter-hidden-"] { display: none; }
110+
.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; }
111+
.filter-list :after { content: ''; }
112+
.filter-list li {
113+
background: var(--tab-disabled-background);
114+
border-bottom: var(--border);
115+
color: var(--tab-disabled-color);
116+
display: none;
117+
list-style: none;
118+
margin: 0;
119+
padding: 5px 10px;
120+
text-align: left;
121+
font-weight: normal;
122+
}
123+
.filter-list li.active {
124+
background: var(--tab-background);
125+
color: var(--tab-color);
126+
}
127+
.filter-list li.last-active {
128+
background: var(--tab-active-background);
129+
color: var(--tab-active-color);
130+
}
131+
132+
.filter-list-level li { cursor: s-resize; }
133+
.filter-list-level li.active { cursor: n-resize; }
134+
.filter-list-level li.last-active { cursor: default; }
135+
.filter-list-level li.last-active:before { content: '\2714\00a0'; }
136+
.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; }
137+
.filter-list-choice li.active:before { color: unset; }
138+
139+
.container { max-width: 1024px; margin: 0 auto; padding: 0 15px; }
140+
.container::after { content: ""; display: table; clear: both; }
141+
142+
header { background-color: var(--base-6); color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; }
143+
header .container { display: flex; justify-content: space-between; }
144+
.logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; }
145+
.logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; }
146+
147+
.help-link { margin-left: 15px; }
148+
.help-link a { color: inherit; }
149+
.help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; }
150+
.help-link a:hover { color: #EEE; text-decoration: none; }
151+
.help-link a:hover svg { opacity: .9; }
152+
153+
.exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; }
154+
.exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; }
155+
.exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; }
156+
.exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; }
157+
.exception-http small { font-size: 13px; opacity: .7; }
158+
.exception-hierarchy { flex: 1; }
159+
.exception-hierarchy .icon { margin: 0 3px; opacity: .7; }
160+
.exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; }
161+
162+
.exception-without-message .exception-message-wrapper { display: none; }
163+
.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; }
164+
.exception-message { flex-grow: 1; }
165+
.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; }
166+
.exception-message.long { font-size: 18px; }
167+
.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; }
168+
.exception-message a:hover { border-bottom-color: #ffffff; }
169+
170+
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
171+
172+
.trace + .trace { margin-top: 30px; }
173+
.trace-head { background-color: var(--base-2); padding: 10px; position: relative; }
174+
.trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
175+
.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; }
176+
.trace-head .icon { position: absolute; right: 0; top: 0; }
177+
.trace-head .icon svg { height: 24px; width: 24px; }
178+
179+
.trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; table-layout: fixed; }
180+
181+
.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }
182+
183+
.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; }
184+
.trace-line + .trace-line { border-top: var(--border); }
185+
.trace-line:hover { background: var(--base-1); }
186+
.trace-line a { color: var(--base-6); }
187+
.trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; }
188+
.trace-line .icon svg { height: 16px; width: 16px; }
189+
.trace-line-header { padding-left: 36px; padding-right: 10px; }
190+
191+
.trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; }
192+
.trace-class { color: var(--color-error); }
193+
.trace-type { padding: 0 2px; }
194+
.trace-method { color: var(--color-error); font-weight: bold; }
195+
.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
196+
197+
.trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; }
198+
.trace-code ol { margin: 0; float: left; }
199+
.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; }
200+
.trace-code li + li { margin-top: 5px; }
201+
.trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; }
202+
.trace-code li code { color: var(--base-6); white-space: nowrap; }
203+
204+
.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; }
205+
206+
@media (min-width: 575px) {
207+
.hidden-xs-down { display: initial; }
208+
.help-link { margin-left: 30px; }
209+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
.sf-reset .traces {
2+
padding-bottom: 14px;
3+
}
4+
.sf-reset .traces li {
5+
font-size: 12px;
6+
color: #868686;
7+
padding: 5px 4px;
8+
list-style-type: decimal;
9+
margin-left: 20px;
10+
}
11+
.sf-reset #logs .traces li.error {
12+
font-style: normal;
13+
color: #AA3333;
14+
background: #f9ecec;
15+
}
16+
.sf-reset #logs .traces li.warning {
17+
font-style: normal;
18+
background: #ffcc00;
19+
}
20+
/* fix for Opera not liking empty <li> */
21+
.sf-reset .traces li:after {
22+
content: "\00A0";
23+
}
24+
.sf-reset .trace {
25+
border: 1px solid #D3D3D3;
26+
padding: 10px;
27+
overflow: auto;
28+
margin: 10px 0 20px;
29+
}
30+
.sf-reset .block-exception {
31+
-moz-border-radius: 16px;
32+
-webkit-border-radius: 16px;
33+
border-radius: 16px;
34+
margin-bottom: 20px;
35+
background-color: #f6f6f6;
36+
border: 1px solid #dfdfdf;
37+
padding: 30px 28px;
38+
word-wrap: break-word;
39+
overflow: hidden;
40+
}
41+
.sf-reset .block-exception div {
42+
color: #313131;
43+
font-size: 10px;
44+
}
45+
.sf-reset .block-exception-detected .illustration-exception,
46+
.sf-reset .block-exception-detected .text-exception {
47+
float: left;
48+
}
49+
.sf-reset .block-exception-detected .illustration-exception {
50+
width: 152px;
51+
}
52+
.sf-reset .block-exception-detected .text-exception {
53+
width: 670px;
54+
padding: 30px 44px 24px 46px;
55+
position: relative;
56+
}
57+
.sf-reset .text-exception .open-quote,
58+
.sf-reset .text-exception .close-quote {
59+
font-family: Arial, Helvetica, sans-serif;
60+
position: absolute;
61+
color: #C9C9C9;
62+
font-size: 8em;
63+
}
64+
.sf-reset .open-quote {
65+
top: 0;
66+
left: 0;
67+
}
68+
.sf-reset .close-quote {
69+
bottom: -0.5em;
70+
right: 50px;
71+
}
72+
.sf-reset .block-exception p {
73+
font-family: Arial, Helvetica, sans-serif;
74+
}
75+
.sf-reset .block-exception p a,
76+
.sf-reset .block-exception p a:hover {
77+
color: #565656;
78+
}
79+
.sf-reset .logs h2 {
80+
float: left;
81+
width: 654px;
82+
}
83+
.sf-reset .error-count, .sf-reset .support {
84+
float: right;
85+
width: 170px;
86+
text-align: right;
87+
}
88+
.sf-reset .error-count span {
89+
display: inline-block;
90+
background-color: #aacd4e;
91+
-moz-border-radius: 6px;
92+
-webkit-border-radius: 6px;
93+
border-radius: 6px;
94+
padding: 4px;
95+
color: white;
96+
margin-right: 2px;
97+
font-size: 11px;
98+
font-weight: bold;
99+
}
100+
101+
.sf-reset .support a {
102+
display: inline-block;
103+
-moz-border-radius: 6px;
104+
-webkit-border-radius: 6px;
105+
border-radius: 6px;
106+
padding: 4px;
107+
color: #000000;
108+
margin-right: 2px;
109+
font-size: 11px;
110+
font-weight: bold;
111+
}
112+
113+
.sf-reset .toggle {
114+
vertical-align: middle;
115+
}
116+
.sf-reset .linked ul,
117+
.sf-reset .linked li {
118+
display: inline;
119+
}
120+
.sf-reset #output-content {
121+
color: #000;
122+
font-size: 12px;
123+
}
124+
.sf-reset #traces-text pre {
125+
white-space: pre;
126+
font-size: 12px;
127+
font-family: monospace;
128+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg==

0 commit comments

Comments
 (0)