• R/O
  • SSH
  • HTTPS

mantisbtmonitor: Commit


Commit MetaInfo

Revision38 (tree)
Time2017-11-23 01:39:14
Authorderekwildstar

Log Message

- Corrigido o problema de carregamento de comentários
- Incluído um texto que alerta sobre os comentários privados
- Corrigido o erro que fazia com que a lista de anexos não forsse recarregada após carregar um novo anexo

Change Summary

Incremental Difference

--- trunk/client/prj/MantisNotification.bdsproj (revision 37)
+++ trunk/client/prj/MantisNotification.bdsproj (revision 38)
@@ -150,7 +150,7 @@
150150 <VersionInfo Name="MajorVer">1</VersionInfo>
151151 <VersionInfo Name="MinorVer">2</VersionInfo>
152152 <VersionInfo Name="Release">3</VersionInfo>
153- <VersionInfo Name="Build">862</VersionInfo>
153+ <VersionInfo Name="Build">922</VersionInfo>
154154 <VersionInfo Name="Debug">False</VersionInfo>
155155 <VersionInfo Name="PreRelease">False</VersionInfo>
156156 <VersionInfo Name="Special">False</VersionInfo>
@@ -162,7 +162,7 @@
162162 <VersionInfoKeys>
163163 <VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
164164 <VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
165- <VersionInfoKeys Name="FileVersion">1.2.3.862</VersionInfoKeys>
165+ <VersionInfoKeys Name="FileVersion">1.2.3.922</VersionInfoKeys>
166166 <VersionInfoKeys Name="InternalName"></VersionInfoKeys>
167167 <VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
168168 <VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
--- trunk/client/prj/MantisNotification.dpr (revision 37)
+++ trunk/client/prj/MantisNotification.dpr (revision 38)
@@ -23,7 +23,7 @@
2323 ValidUser: Boolean;
2424 begin
2525 Application.Initialize;
26- Application.Title := 'Projeto TMN2017';
26+ Application.Title := 'Projeto TMN2018';
2727 ValidUser := (Configurations.Profile <> pUnknown) and (Configurations.UserId > 0);
2828
2929 if not ValidUser then
--- trunk/client/src/lib/UFunctions.pas (revision 37)
+++ trunk/client/src/lib/UFunctions.pas (revision 38)
@@ -6,6 +6,16 @@
66 SHDocVw, DBClient;
77
88 type
9+ TSanitizeFlag = (sfUnknown
10+ ,sfDeactivateLinks = 1
11+ ,sfDeactivateOtherTags = 2
12+ ,sfActivateAllowedTags = 4
13+ ,sfActivateLinks = 8
14+ ,sfMakeSpacesAndTabsPreserved = 16
15+ ,sfMakeReturnsPreserved = 32);
16+
17+ TSanitizeFlags = set of TSanitizeFlag;
18+
919 TIssueInfo = record
1020 Id: Integer;
1121 ProjectName: String;
@@ -23,7 +33,7 @@
2333 procedure OpenIssueWithMantis(AIssueNumber: Cardinal);
2434 procedure DownloadAttachment(AAttachmentId: Cardinal; AFileName: String; AOpen: Boolean = True);
2535 function UploadAttachment(AIssueNumber: Cardinal; AFileName: String): Cardinal;
26-procedure LoadWebBrowserHTML(AWebBrowser: TWebBrowser; AText: String; ADecode: Boolean = False);
36+procedure LoadWebBrowserHTML(AWebBrowser: TWebBrowser; AText: String; ASanitizeFlags: TSanitizeFlags = [sfDeactivateLinks,sfDeactivateOtherTags,sfActivateAllowedTags,sfMakeSpacesAndTabsPreserved,sfMakeReturnsPreserved,sfActivateLinks]; ADecode: Boolean = False; ABackgroundColor: String = '#FFFFFF');
2737 procedure GenerateSimpleComments(AWebBrowser: TWebBrowser; AClientDataSet: TClientDataSet);
2838
2939 implementation
@@ -65,18 +75,22 @@
6575 end;
6676 end;
6777
68-function RegExReplaceAll(ASubject, APattern, AReplacement: String; out AResult: String; ASingleLine: Boolean = True; ACaseInsensitive: Boolean = True): Boolean;
78+function RegExReplaceAll(ASubject, APattern, AReplacement: String; out AResult: String; ASingleLine: Boolean = True; ACaseInsensitive: Boolean = True; AUnGreedy: Boolean = False): Boolean;
6979 begin
7080 Result := False;
71- AResult := '';
81+ AResult := ASubject;
7282
7383 with TPerlRegEx.Create do
7484 try
7585 if ASingleLine then
7686 Options := Options + [preSingleLine];
87+
7788 if ACaseInsensitive then
7889 Options := Options + [preCaseLess];
7990
91+ if AUnGreedy then
92+ Options := Options + [preUnGreedy];
93+
8094 Subject := ASubject;
8195 RegEx := APattern;
8296 Replacement := AReplacement;
@@ -91,14 +105,14 @@
91105 end;
92106 // Protege AProtectPattern enquanto realiza a substituição de AOldPattern por
93107 // AReplacement, colocando o resultado final em AResult
94-function RegExProtectAndReplace(ASubject, AProtectPattern, AOldPattern, AReplacement: String; AProtectedSingleLine: Boolean = True; AProtectedCaseInsensitive: Boolean = True; AReplaceSingleLine: Boolean = True; AReplaceCaseInsensitive: Boolean = True): String;
108+function RegExProtectAndReplace(ASubject, AProtectPattern, AOldPattern, AReplacement: String; AProtectedSingleLine: Boolean = True; AProtectedCaseInsensitive: Boolean = True; AProtectedUnGreedy: Boolean = False; AReplaceSingleLine: Boolean = True; AReplaceCaseInsensitive: Boolean = True; AReplaceUnGreedy: Boolean = False): String;
95109 const
96110 PROTECTEDPLACEHOLDER = '[¯:_:¯]';
97111 var
98112 ProtectedTexts: array of string;
99-// -----------------------------------------------------------------------------
100-// Protege o texto substituindo cada ocorrência de APattern por <:protected:> e
101-// salva o texto substitído no array AProtectedTexts
113+////////////////////////////////////////////////////////////////////////////////
114+// Protege o texto substituindo cada ocorrência de APattern por
115+// PROTECTEDPLACEHOLDER e salva o texto substitído no array AProtectedTexts
102116 function Protect: String;
103117 begin
104118 Result := ASubject;
@@ -107,9 +121,13 @@
107121 try
108122 if AProtectedSingleLine then
109123 Options := Options + [preSingleLine];
124+
110125 if AProtectedCaseInsensitive then
111126 Options := Options + [preCaseLess];
112127
128+ if AProtectedUnGreedy then
129+ Options := Options + [preUnGreedy];
130+
113131 Subject := Result;
114132 RegEx := AProtectPattern;
115133 Replacement := PROTECTEDPLACEHOLDER;
@@ -136,9 +154,13 @@
136154 try
137155 if AReplaceSingleLine then
138156 Options := Options + [preSingleLine];
157+
139158 if AReplaceCaseInsensitive then
140159 Options := Options + [preCaseLess];
141160
161+ if AReplaceUnGreedy then
162+ Options := Options + [preUnGreedy];
163+
142164 Subject := Result;
143165 RegEx := AOldPattern;
144166 Replacement := AReplacement;
@@ -164,7 +186,7 @@
164186 Inc(i);
165187 end;
166188 end;
167-// -----------------------------------------------------------------------------
189+////////////////////////////////////////////////////////////////////////////////
168190 begin
169191 ASubject := Protect;
170192 ASubject := Replace;
@@ -199,98 +221,235 @@
199221 // return $p_string;
200222 // }
201223 //
202-function SanitizeString(AString: String; AFlags: Byte): String;
203-const
204- ALOWABLETAGS = 'p|li|ul|ol|br|pre|i|b|u|em';
224+function SanitizeString(AString: String; AFlags: Word): String;
225+////////////////////////////////////////////////////////////////////////////////
226+procedure RemoveLinks(var S: String);
205227 var
206228 Subject: String;
207229 begin
208- esta função está retonando uma string vazia
209- revise ela, ela deve trabalar em AString e ao final retornar (Result) com a string trabalhada
210- acho que o que eu fiz abaixo deixou as coisas complexas, usar uma variável diferente só é necessário
211- por conta da função RegExReplaceAll que requer isso
212-
213-
214- Result := AString;
215- Subject := Result;
216-
217- // Remove links e deixa apenas os texto puro
218230 if AFlags and 1 = 1 then
219231 begin
220- RegExReplaceAll(Subject,'<a\s[^\>]*href="mailto\:([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',Result);
232+ Subject := S;
221233
222- Subject := Result;
234+ RegExReplaceAll(Subject,'<a\s[^\>]*href="mailto\:([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',S);
223235
224- RegExReplaceAll(Subject,'<a\s[^\>]*href="([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',Result);
236+ Subject := S;
225237
226- Subject := Result;
238+ RegExReplaceAll(Subject,'<a\s[^\>]*href="([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',S);
227239 end;
240+end;
228241
229- // Transforma todos os tags HTML em texto plano
242+procedure DeactivateAllTags(var S: String);
243+begin
230244 if AFlags and 2 = 2 then
231245 begin
232- Result := StringReplace(Subject,'&','&amp;',[rfReplaceAll]);
233- Result := StringReplace(Result,'"','&quot;',[rfReplaceAll]);
234- Result := StringReplace(Result,#39,'&apos;',[rfReplaceAll]);
235- Result := StringReplace(Result,'<','&lt;',[rfReplaceAll]);
236- Subject := StringReplace(Result,'>','&gt;',[rfReplaceAll]);
237-
238- Result := Subject;
246+ S := StringReplace(S,'&','&amp;',[rfReplaceAll]);
247+ S := StringReplace(S,'"','&quot;',[rfReplaceAll]);
248+ S := StringReplace(S,#39,'&apos;',[rfReplaceAll]);
249+ S := StringReplace(S,'<','&lt;',[rfReplaceAll]);
250+ S := StringReplace(S,'>','&gt;',[rfReplaceAll]);
239251 end;
252+end;
240253
241- // Transforma os tags listados que estão em formato de texto plano em tags
242- // html novamente. Em outras palavras, pega um texto sem os tags html e
243- // recupera apenas aqueles que são permitidos
254+procedure ActivateAllowedTags(var S: String);
255+const
256+ ALOWABLETAGS = 'p|li|ul|ol|br|pre|i|b|u|em|div|span'; {TODO: Aparentemente o mantis não coloca isso em uma configuração, mas se colocar, faça algo para obter essa lista }
257+var
258+ Subject: String;
259+begin
244260 if AFlags and 4 = 4 then
245261 begin
246- RegExReplaceAll(Subject,'&lt;(' + ALOWABLETAGS + ')\s*&gt;','<\1>',Result); // <tagname>
262+ Subject := S;
247263
248- Subject := Result;
264+ RegExReplaceAll(Subject,'&lt;((' + ALOWABLETAGS + ').*)&gt;','<\1>',S,True,True,True); // <tagname>
249265
250- RegExReplaceAll(Subject,'&lt;\/(' + ALOWABLETAGS + ')\s*&gt;','</\1>',Result); // </tagname>
266+ Subject := S;
251267
252- Subject := Result;
268+ RegExReplaceAll(Subject,'&lt;\/(' + ALOWABLETAGS + ').*&gt;','</\1>',S,True,True,True); // </tagname>
253269
254- RegExReplaceAll(Subject,'&lt;(' + ALOWABLETAGS + ')\s*\/&gt;','<\1 />',Result); // <tagname />
270+ Subject := S;
255271
256- Subject := Result;
272+ RegExReplaceAll(Subject,'&lt;(' + ALOWABLETAGS + ').*\/&gt;','<\1 />',S,True,True,True); // <tagname />
273+
274+ Subject := S;
275+
276+ RegExReplaceAll(Subject,'&quot;(?=[^<]*>)','"',S,True,True,True); // transforma &quot;, dentro de tags, novamente em aspas duplas!
277+ // For anyone curious how this works. This translates into English as "Find a quote that is followed by a > before the next <".
278+
279+ Subject := S;
280+
281+ RegExReplaceAll(Subject,'&apos;(?=[^<]*>)','"',S,True,True,True); // transforma &apos;, dentro de tags, novamente em apóstrofo!
257282 end;
283+end;
258284
259- // Preserva espaços e Tabs. A implementação original era mais complexa porque
260- // considerava apenas os tabs e espaços no início da linha, no entanto, isso
261- // só foi feito porque a implementação em PHP não deve gerar mais dados que o
262- // necessário, para evitar consumo de banda desnecessário. Como aqui estamos
263- // apenas exibindo na tela, optei por substituir tudo mesmo
285+procedure AddLinks(var S: String);
286+var
287+ Subject: String;
288+begin
264289 if AFlags and 8 = 8 then
265290 begin
266- Result := StringReplace(Subject,#32,'&nbsp;',[rfReplaceAll]);
267- Subject := StringReplace(Result,#9,'&nbsp;&nbsp;&nbsp;&nbsp;',[rfReplaceAll]); // 1 tab = 4 espaços
291+ Subject := S;
268292
269- Result := Subject;
270- end;
293+ RegExReplaceAll(Subject,'(\b(?:https?|ftps?):\/\/[a-z0-9-_.]*\b)','<a href="\1">\1</a> [<a href="\1" target="_blank">^</a>]',S,False);
271294
272- // Substitui cada quebra de linha por uma quebra de linha + um <br>, sem
273- // afetar o conteúdo de tags <pre>
295+ Subject := S;
296+
297+ RegExReplaceAll(Subject,'(\b[a-zA-Z0-9.]*@[a-zA-Z0-9.]*\b)','<a href="mailto:\1">\1</a>',S,False);
298+ + end;
299+end;
300+
301+procedure MakeSpacesAndTabsPreserved(var S: String);
302+var
303+ Subject: String;
304+begin
274305 if AFlags and 16 = 16 then
275306 begin
276- Subject := RegExProtectAndReplace(Subject,'(<pre[^>]*>.*?<\/pre>)',#13#10,'<br>'#13#10);
307+ Subject := S;
277308
278- Result := Subject;
309+ S := RegExProtectAndReplace(Subject,'<.*>',#32,'&nbsp;',True,False,True);
310+
311+ Subject := S;
312+
313+ S := RegExProtectAndReplace(Subject,'<.*>',#9,'&nbsp;&nbsp;&nbsp;&nbsp;',True,False,True); // 1 tab = 4 espaços
279314 end;
315+end;
280316
281- // Detecta urls e e-mails e os transforma novamente em links
317+procedure MakeReturnsPreserved(var S: String);
318+var
319+ Subject: String;
320+begin
282321 if AFlags and 32 = 32 then
283322 begin
284- RegExReplaceAll(Subject,'(\b(?:https?|ftps?):\/\/[a-z0-9-_.]*\b)','<a href="\1">\1</a> [<a href="\1" target="_blank">^</a>]',Result,False);
323+ Subject := S;
285324
286- Subject := Result;
325+ S := RegExProtectAndReplace(Subject,'(<pre[^>]*>.*?<\/pre>)',#13#10,'<br>'#13#10);
326+ end;
327+end;
328+////////////////////////////////////////////////////////////////////////////////
329+begin
330+ // Remove os links ativos, isto é, aqueles que estão de fato contidos em tags
331+ // <a>. Isso é uma forma de proteger os links também, pois posteriormente todos
332+ // os tags serão validados (dasativados e ativados) e os tags <a> são um caso
333+ // especial que será tratado posteriormente
334+ RemoveLinks(AString);
335+ // Desativa todos os os tags html. O efeito deste procedure é substituir os
336+ // elementos ativos do HTML por entidades HTML correspondentes (inativas), por
337+ // exemplo, "<" é transformado em "&lt;"
338+ DeactivateAllTags(AString);
339+ // Transforma as entidades html em caracteres html ativos, apenas dos tags
340+ // permitidos. Em outras palavras, pega um texto sem os tags html e recupera
341+ // apenas aqueles que são permitidos
342+ ActivateAllowedTags(AString);
343+ // Detecta urls e e-mails e os transforma novamente em links
344+ AddLinks(AString);
287345
288- RegExReplaceAll(Subject,'(\b.*@.*\b)','<a href="mailto:\1">\1</a>',Result,False);
346+ // Os procedures abaixo só podem ser executados em strings onde os tags já
347+ // foram validados e substituídos, pois consideram a existência de caracteres
348+ // < e > a fim de protegê-los
289349
290- Subject := Result;
291- end;
350+ // Preserva espaços e Tabs. Este procedure preserva os espaços e tabs FORA de
351+ // qualquer tag válido
352+ MakeSpacesAndTabsPreserved(AString);
353+ // Substitui cada quebra de linha por uma quebra de linha + um <br>, sem
354+ // afetar o conteúdo de tags <pre>
355+ MakeReturnsPreserved(AString);
356+
357+ Result := AString;
292358 end;
293359
360+//function SanitizeString(AString: String; AFlags: Byte): String;
361+//const
362+// ALOWABLETAGS = 'p|li|ul|ol|br|pre|i|b|u|em';
363+//var
364+// Subject: String;
365+//begin
366+// esta função está retonando uma string vazia
367+// revise ela, ela deve trabalar em AString e ao final retornar (Result) com a string trabalhada
368+// acho que o que eu fiz abaixo deixou as coisas complexas, usar uma variável diferente só é necessário
369+// por conta da função RegExReplaceAll que requer isso
370+//
371+// Result := AString;
372+// Subject := Result;
373+//
374+// // Remove links e deixa apenas os texto puro
375+// if AFlags and 1 = 1 then
376+// begin
377+// RegExReplaceAll(Subject,'<a\s[^\>]*href="mailto\:([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',Result);
378+//
379+// Subject := Result;
380+//
381+// RegExReplaceAll(Subject,'<a\s[^\>]*href="([^\"]+)"[^\>]*>[^\<]*<\/a>','\1',Result);
382+//
383+// Subject := Result;
384+// end;
385+//
386+// // Transforma todos os tags HTML em texto plano
387+// if AFlags and 2 = 2 then
388+// begin
389+// Result := StringReplace(Subject,'&','&amp;',[rfReplaceAll]);
390+// Result := StringReplace(Result,'"','&quot;',[rfReplaceAll]);
391+// Result := StringReplace(Result,#39,'&apos;',[rfReplaceAll]);
392+// Result := StringReplace(Result,'<','&lt;',[rfReplaceAll]);
393+// Subject := StringReplace(Result,'>','&gt;',[rfReplaceAll]);
394+//
395+// Result := Subject;
396+// end;
397+//
398+// // Transforma os tags listados que estão em formato de texto plano em tags
399+// // html novamente. Em outras palavras, pega um texto sem os tags html e
400+// // recupera apenas aqueles que são permitidos
401+// if AFlags and 4 = 4 then
402+// begin
403+// RegExReplaceAll(Subject,'&lt;(' + ALOWABLETAGS + ')\s*&gt;','<\1>',Result); // <tagname>
404+//
405+// Subject := Result;
406+//
407+// RegExReplaceAll(Subject,'&lt;\/(' + ALOWABLETAGS + ')\s*&gt;','</\1>',Result); // </tagname>
408+//
409+// Subject := Result;
410+//
411+// RegExReplaceAll(Subject,'&lt;(' + ALOWABLETAGS + ')\s*\/&gt;','<\1 />',Result); // <tagname />
412+//
413+// Subject := Result;
414+// end;
415+//
416+// // Preserva espaços e Tabs. A implementação original era mais complexa porque
417+// // considerava apenas os tabs e espaços no início da linha, no entanto, isso
418+// // só foi feito porque a implementação em PHP não deve gerar mais dados que o
419+// // necessário, para evitar consumo de banda desnecessário. Como aqui estamos
420+// // apenas exibindo na tela, optei por substituir tudo mesmo
421+// if AFlags and 8 = 8 then
422+// begin
423+// Result := StringReplace(Subject,#32,'&nbsp;',[rfReplaceAll]);
424+// Subject := StringReplace(Result,#9,'&nbsp;&nbsp;&nbsp;&nbsp;',[rfReplaceAll]); // 1 tab = 4 espaços
425+//
426+// Result := Subject;
427+// end;
428+//
429+// // Substitui cada quebra de linha por uma quebra de linha + um <br>, sem
430+// // afetar o conteúdo de tags <pre>
431+// if AFlags and 16 = 16 then
432+// begin
433+// Subject := RegExProtectAndReplace(Subject,'(<pre[^>]*>.*?<\/pre>)',#13#10,'<br>'#13#10);
434+//
435+// Result := Subject;
436+// end;
437+//
438+// // Detecta urls e e-mails e os transforma novamente em links
439+// if AFlags and 32 = 32 then
440+// begin
441+// RegExReplaceAll(Subject,'(\b(?:https?|ftps?):\/\/[a-z0-9-_.]*\b)','<a href="\1">\1</a> [<a href="\1" target="_blank">^</a>]',Result,False);
442+//
443+// Subject := Result;
444+//
445+// RegExReplaceAll(Subject,'(\b.*@.*\b)','<a href="mailto:\1">\1</a>',Result,False);
446+ +//
447+// Subject := Result;
448+// end;
449+//end;
450+
294451 procedure OpenIssueWithMantis(AIssueNumber: Cardinal);
295452 const
296453 URL = 'https://www.tjpe.jus.br/mantis/view.php?id=%u';
@@ -388,7 +547,7 @@
388547 ,FileContents);
389548 end;
390549
391-procedure LoadWebBrowserHTML(AWebBrowser: TWebBrowser; AText: String; ADecode: Boolean = False);
550+procedure LoadWebBrowserHTML(AWebBrowser: TWebBrowser; AText: String; ASanitizeFlags: TSanitizeFlags = [sfDeactivateLinks,sfDeactivateOtherTags,sfActivateAllowedTags,sfMakeSpacesAndTabsPreserved,sfMakeReturnsPreserved,sfActivateLinks]; ADecode: Boolean = False; ABackgroundColor: String = '#FFFFFF');
392551 ////////////////////////////////////////////////////////////////////////////////
393552 function GetCorrectHTML(ABody: String): String;
394553 const
@@ -395,11 +554,14 @@
395554 HTML = '<html>'
396555 + '<head>'
397556 + '<style type="text/css">'
398- + 'body {margin: 5pt; font-size: 10pt; font-family: Verdana, Arial, Helvetica, sans-serif}'
557+ + 'body {margin: 5pt; font-size: 10pt; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: %s}'
399558 + '</style>'
400559 + '</head>'
401560 + '<body>%s</body>'
402561 + '</html>';
562+var
563+ SF: Word;
564+ SanitizeFlag: TSanitizeFlag;
403565 begin
404566 if ADeCode then
405567 ABody := StringReplace(UTF8Decode(DecodeString(ABody)),#13#10,'<br>',[rfReplaceAll])
@@ -406,8 +568,17 @@
406568 else
407569 ABody := StringReplace(ABody,#13#10,'<br>',[rfReplaceAll]);
408570
409- ABody := SanitizeString(ABody,6);
410- Result := Format(HTML,[ABody]);
571+ // Ao depurar o loop abaixo, notei que ele circula por todos os valores
572+ // possíveis de TSanitizeFlag, de zero a 32, mas só de fato entra no loop para
573+ // incrementar SF para os flags que foram definidos. Em suma, funciona, mas é
574+ // um pouco estrnho e dispendioso em termos de performance, contudo, nada que
575+ // prejudique o sistema
576+ SF := 0;
577+ for SanitizeFlag in ASanitizeFlags do
578+ Inc(SF,Integer(SanitizeFlag));
579+
580+ ABody := SanitizeString(ABody,SF);
581+ Result := Trim(Format(HTML,[ABackgroundColor,ABody]));
411582 end;
412583 ////////////////////////////////////////////////////////////////////////////////
413584 var
@@ -429,7 +600,7 @@
429600
430601 procedure GenerateSimpleComments(AWebBrowser: TWebBrowser; AClientDataSet: TClientDataSet);
431602 const
432- COMMENT = '<div style="background-color: %s; font-weight: bold; color: #FFFFFF; padding: 5px">(%s) <span style="color: #FFFF00">%s</span> respondeu em <span style="color: #FFFF00">%s</span></div><div>%s</div><br>';
603+ COMMENT = '<div style="background-color: %s; font-weight: bold; color: #FFFFFF; padding: 5px">(%s) <span style="color: #FFFF00">%s</span> respondeu em <span style="color: #FFFF00">%s</span></div><div style="background-color: #F0F0F0">%s</div><br>';
433604 var
434605 Comments: String;
435606 Color: String;
--- trunk/client/src/UFormIssue.pas (revision 37)
+++ trunk/client/src/UFormIssue.pas (revision 38)
@@ -99,6 +99,8 @@
9999 PNSBNoteFirst: TPngSpeedButton;
100100 ACTNNoteEdit: TAction;
101101 PNBBNoteEdit: TPngBitBtn;
102+ LABE3: TLabel;
103+ PANE2: TPanel;
102104 procedure ACTNNoteEditExecute(Sender: TObject);
103105 procedure ACTNNoteNewExecute(Sender: TObject);
104106 procedure PNSBNoteFirstClick(Sender: TObject);
@@ -189,7 +191,7 @@
189191 LABENoteAuthor.Caption := CLDSCommentsReporter.AsString;
190192 LABENoteDate.Caption := FormatDateTime('dd/mm/yyyy "às" hh:nn:ss',CLDSCommentsDate.AsDateTime);
191193 LABENoteNumber.Caption := '(' + FormatFloat('00000000',CLDSCommentsid.AsInteger) + ')';
192- LoadWebBrowserHTML(WEBRNote,CLDSCommentsNote.AsString,True);
194+ LoadWebBrowserHTML(WEBRNote,CLDSCommentsNote.AsString,[sfDeactivateLinks,sfDeactivateOtherTags,sfActivateAllowedTags,sfMakeSpacesAndTabsPreserved,sfMakeReturnsPreserved,sfActivateLinks],True);
193195 PNBBNoteReply.Tag := CLDSCommentsId.AsInteger;
194196 PNBBNoteFullScreen.Tag := CLDSCommentsId.AsInteger;
195197 PNBBNoteEdit.Tag := CLDSCommentsId.AsInteger;
@@ -226,8 +228,7 @@
226228 TFormIssue.ShowMe(CLDSRelatedIssuesNumber.AsInteger);
227229 end;
228230
229-procedure TFormIssue.KRDGRelatedIssuesDrawColumnCell(Sender: TObject;
230- const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
231+procedure TFormIssue.KRDGRelatedIssuesDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
231232 begin
232233 inherited;
233234 KRDGRelatedIssues.Canvas.Font.Color := clWindowText;
@@ -304,6 +305,7 @@
304305 if OPDIAttachment.Execute then
305306 begin
306307 UploadAttachment(FIssueInfo.Id,OPDIAttachment.FileName);
308+ FAttachmentsLoaded := False;
307309 LoadAttachments;
308310 end;
309311 end;
--- trunk/client/src/UFormViewNote.pas (revision 37)
+++ trunk/client/src/UFormViewNote.pas (revision 38)
@@ -58,7 +58,7 @@
5858 LABENoteAuthor.Caption := CLDSCommentsReporter.AsString;
5959 LABENoteDate.Caption := FormatDateTime('dd/mm/yyyy "às" hh:nn:ss',CLDSCommentsDate.AsDateTime);
6060 LABECaption.Caption := Format(FCaptionTemplate,[FormatFloat('00000000',CLDSCommentsid.AsInteger),Abs(CLDSComments.RecordCount - CLDSComments.RecNo + 1),CLDSComments.RecordCount]);
61- LoadWebBrowserHTML(WEBRNote,CLDSCommentsNote.AsString,True);
61+ LoadWebBrowserHTML(WEBRNote,CLDSCommentsNote.AsString,[sfDeactivateLinks,sfDeactivateOtherTags,sfActivateAllowedTags,sfMakeSpacesAndTabsPreserved,sfMakeReturnsPreserved,sfActivateLinks],True);
6262
6363 if CLDSCommentsPrivate.AsInteger = 1 then
6464 PANE.Color := clGray
Show on old repository browser