44import com .genexus .internet .HttpContext ;
55import com .genexus .reports .*;
66import com .genexus .webpanels .GXWebProcedure ;
7+ import org .apache .logging .log4j .Logger ;
8+
9+ import java .io .UnsupportedEncodingException ;
10+ import java .net .URLEncoder ;
11+ import java .nio .charset .StandardCharsets ;
12+
13+ public abstract class GXWebReport extends GXWebProcedure {
14+ private static Logger log = org .apache .logging .log4j .LogManager .getLogger (GXWebReport .class );
715
8- public abstract class GXWebReport extends GXWebProcedure
9- {
1016 public static final int OUTPUT_RVIEWER = 1 ;
11- public static final int OUTPUT_PDF = 2 ;
17+ public static final int OUTPUT_PDF = 2 ;
1218
1319 // Tiene que ser protected porque se pasa como par�metro en los reports
1420 protected GXReportMetadata reportMetadata ;
1521 protected IReportHandler reportHandler ;
1622
1723 protected int lineHeight ;
18- protected int Gx_line ;
19- protected int P_lines ;
20- protected int gxXPage ;
21- protected int gxYPage ;
22- protected int Gx_page ;
23- protected String Gx_out = "" ; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask.
24+ protected int Gx_line ;
25+ protected int P_lines ;
26+ protected int gxXPage ;
27+ protected int gxYPage ;
28+ protected int Gx_page ;
29+ protected String Gx_out = "" ; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask.
2430 protected String filename ;
2531 protected String filetype ;
2632
27- public GXWebReport (HttpContext httpContext )
28- {
33+ public GXWebReport (HttpContext httpContext ) {
2934 super (httpContext );
3035 }
3136
32- protected void initState (ModelContext context , UserInformation ui )
33- {
37+ protected void initState (ModelContext context , UserInformation ui ) {
3438 super .initState (context , ui );
3539
3640 httpContext .setResponseBufferMode (HttpContext .ResponseBufferMode .ENABLED );
@@ -45,140 +49,163 @@ else if (implementation.equals("ITEXT8"))
4549 initValues ();
4650 }
4751
48- protected void preExecute ()
49- {
52+ protected void preExecute () {
5053 httpContext .setContentType ("application/pdf" );
5154 httpContext .setStream ();
5255 ((GXReportPDFCommons ) reportHandler ).setOutputStream (httpContext .getOutputStream ());
5356 }
5457
55- protected void setOutputFileName (String outputFileName ){
58+ protected void setOutputFileName (String outputFileName ) {
5659 filename = outputFileName ;
5760 }
58- protected void setOutputType (String outputType ){
61+ protected void setOutputType (String outputType ) {
5962 filetype = outputType .toLowerCase ();
6063 }
61- private void initValues ()
62- {
63- Gx_line = 0 ;
64- P_lines = 0 ;
65- gxXPage = 0 ;
66- gxYPage = 0 ;
67- Gx_page = 0 ;
68- Gx_out = "" ; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask.
69- lineHeight = 0 ;
64+ private void initValues () {
65+ Gx_line = 0 ;
66+ P_lines = 0 ;
67+ gxXPage = 0 ;
68+ gxYPage = 0 ;
69+ Gx_page = 0 ;
70+ Gx_out = "" ; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask.
71+ lineHeight = 0 ;
7072 }
7173
72- public void setPrinter (IReportHandler reportHandler )
73- {
74+ public void setPrinter (IReportHandler reportHandler ) {
7475 this .reportHandler = reportHandler ;
7576 }
7677
77- public IReportHandler getPrinter ()
78- {
78+ public IReportHandler getPrinter () {
7979 return reportHandler ;
8080 }
8181
82- protected void GxEndPage () throws ProcessInterruptedException
83- {
84- if (reportHandler != null )
82+ protected void GxEndPage () throws ProcessInterruptedException {
83+ if (reportHandler != null )
8584 reportHandler .GxEndPage ();
8685 }
8786
88- protected boolean initTextPrinter (String output , int gxXPage , int gxYPage , String iniFile , String form , String printer , int mode , int nPaperLength , int nPaperWidth , int nGridX , int nGridY , int nPageLines )
89- {
90- int x [] = {gxXPage };
91- int y [] = {gxYPage };
87+ protected boolean initTextPrinter (String output , int gxXPage , int gxYPage , String iniFile , String form , String printer , int mode , int nPaperLength , int nPaperWidth , int nGridX , int nGridY , int nPageLines ) {
88+ int x [] = {
89+ gxXPage
90+ };
91+ int y [] = {
92+ gxYPage
93+ };
9294
9395 getPrinter ().GxRVSetLanguage (localUtil ._language );
94- boolean ret = getPrinter ().GxPrTextInit (output , x , y , iniFile , form , printer , mode , nPaperLength , nPaperWidth , nGridX , nGridY , nPageLines );
96+ boolean ret = getPrinter ().GxPrTextInit (output , x , y , iniFile , form , printer , mode , nPaperLength , nPaperWidth , nGridX , nGridY , nPageLines );
9597
9698 this .gxXPage = x [0 ];
9799 this .gxYPage = y [0 ];
98100
99101 return ret ;
100102 }
101103
102- protected boolean initPrinter (String output , int gxXPage , int gxYPage , String iniFile , String form , String printer , int mode , int orientation , int pageSize , int pageLength , int pageWidth , int scale , int copies , int defSrc , int quality , int color , int duplex )
103- {
104- int x [] = {gxXPage };
105- int y [] = {gxYPage };
106- setResponseOuputFileName ();
104+ protected boolean initPrinter (String output , int gxXPage , int gxYPage , String iniFile , String form , String printer , int mode , int orientation , int pageSize , int pageLength , int pageWidth , int scale , int copies , int defSrc , int quality , int color , int duplex ) {
105+ int x [] = {
106+ gxXPage
107+ };
108+ int y [] = {
109+ gxYPage
110+ };
111+ setResponseOutputFileName ();
107112
108113 getPrinter ().GxRVSetLanguage (localUtil ._language );
109- boolean ret = getPrinter ().GxPrintInit (output , x , y , iniFile , form , printer , mode , orientation , pageSize , pageLength , pageWidth , scale , copies , defSrc , quality , color , duplex );
114+ boolean ret = getPrinter ().GxPrintInit (output , x , y , iniFile , form , printer , mode , orientation , pageSize , pageLength , pageWidth , scale , copies , defSrc , quality , color , duplex );
110115
111116 this .gxXPage = x [0 ];
112117 this .gxYPage = y [0 ];
113118
114119 return ret ;
115120 }
116121
117- private void setResponseOuputFileName (){
118- String outputFileName = filename !=null ? filename : getClass ().getSimpleName ();
119- String outputFileType = filetype !=null ? "." + filetype .toLowerCase (): ".pdf" ;
120- httpContext .getResponse ().addHeader ("content-disposition" , "inline; filename=" + outputFileName + outputFileType );
121- }
122-
123- protected void endPrinter ()
124- {
122+ private void setResponseOutputFileName () {
123+ String outputFileName = (filename != null ? filename : getClass ().getSimpleName ());
124+ String outputFileType = (filetype != null ? "." + filetype .toLowerCase () : ".pdf" );
125+
126+ try {
127+ String encodedFileName = URLEncoder .encode (outputFileName , "UTF-8" ).replace ("+" , "%20" );
128+ boolean isAscii = StandardCharsets .US_ASCII .newEncoder ().canEncode (outputFileName );
129+ String fallbackFileName = outputFileName ;
130+ if (!isAscii ) {
131+ fallbackFileName = outputFileName .replaceAll ("[^\\ p{ASCII}]" , "" );
132+ if (fallbackFileName .isEmpty ()) {
133+ fallbackFileName = "download" ;
134+ }
135+ }
136+ String contentDispositionValue =
137+ "inline; filename=\" " + fallbackFileName + outputFileType + "\" ; " +
138+ "filename*=UTF-8''" + encodedFileName + outputFileType ;
139+
140+ httpContext .getResponse ().addHeader ("Content-Disposition" , contentDispositionValue );
141+ } catch (UnsupportedEncodingException e ) {
142+ httpContext .getResponse ().addHeader ("Content-Disposition" , "inline; filename=\" download" + outputFileType + "\" " );
143+ }
144+ }
145+
146+ /**
147+ * Returns an ASCII version of the filename.
148+ * Non-ASCII characters are replaced with underscore to ensure ASCII compliance.
149+ */
150+ private String asciiFileName (String fileName ) {
151+ StringBuilder asciiFileName = new StringBuilder ();
152+ for (char character : fileName .toCharArray ()) {
153+ if ((character <= 127 )) {
154+ asciiFileName .append (character );
155+ } else {
156+ asciiFileName .append ("_" );
157+ }
158+ }
159+ return asciiFileName .toString ();
160+ }
161+
162+ protected void endPrinter () {
125163 getPrinter ().GxEndPrinter ();
126164 }
127165
128- protected int getOutputType ()
129- {
166+ protected int getOutputType () {
130167 return OUTPUT_RVIEWER ;
131168 }
132169
133- protected java .io .OutputStream getOutputStream ()
134- {
170+ protected java .io .OutputStream getOutputStream () {
135171 throw new RuntimeException ("Output stream not set" );
136172 }
137-
173+
138174 //M�todos para la implementaci�n de reportes din�micos
139- protected void loadReportMetadata (String name )
140- {
175+ protected void loadReportMetadata (String name ) {
141176 reportMetadata = new GXReportMetadata (name , reportHandler );
142177 reportMetadata .load ();
143178 }
144-
145- protected int GxDrawDynamicGetPrintBlockHeight (int printBlock )
146- {
179+
180+ protected int GxDrawDynamicGetPrintBlockHeight (int printBlock ) {
147181 return reportMetadata .GxDrawGetPrintBlockHeight (printBlock );
148- }
149-
150- protected void GxDrawDynamicText (int printBlock , int controlId , int Gx_line )
151- {
182+ }
183+
184+ protected void GxDrawDynamicText (int printBlock , int controlId , int Gx_line ) {
152185 reportMetadata .GxDrawText (printBlock , controlId , Gx_line );
153186 }
154-
155- protected void GxDrawDynamicText (int printBlock , int controlId , String value , int Gx_line )
156- {
187+
188+ protected void GxDrawDynamicText (int printBlock , int controlId , String value , int Gx_line ) {
157189 reportMetadata .GxDrawText (printBlock , controlId , Gx_line , value );
158190 }
159-
160- protected void GxDrawDynamicLine (int printBlock , int controlId , int Gx_line )
161- {
191+
192+ protected void GxDrawDynamicLine (int printBlock , int controlId , int Gx_line ) {
162193 reportMetadata .GxDrawLine (printBlock , controlId , Gx_line );
163194 }
164-
165- protected void GxDrawDynamicRect (int printBlock , int controlId , int Gx_line )
166- {
195+
196+ protected void GxDrawDynamicRect (int printBlock , int controlId , int Gx_line ) {
167197 reportMetadata .GxDrawRect (printBlock , controlId , Gx_line );
168- }
169-
170- protected void GxDrawDynamicBitMap (int printBlock , int controlId , String value , int Gx_line )
171- {
198+ }
199+
200+ protected void GxDrawDynamicBitMap (int printBlock , int controlId , String value , int Gx_line ) {
172201 reportMetadata .GxDrawBitMap (printBlock , controlId , Gx_line , value , 0 );
173202 }
174-
175- protected void GxDrawDynamicBitMap (int printBlock , int controlId , String value , int aspectRatio , int Gx_line )
176- {
203+
204+ protected void GxDrawDynamicBitMap (int printBlock , int controlId , String value , int aspectRatio , int Gx_line ) {
177205 reportMetadata .GxDrawBitMap (printBlock , controlId , Gx_line , value , aspectRatio );
178- }
179-
180- protected void cleanup ( )
181- {
206+ }
207+
208+ protected void cleanup () {
182209 super .cleanup ();
183210 }
184- }
211+ }
0 commit comments