1 |
dpavlin |
1 |
# Gedafe, the Generic Database Frontend |
2 |
|
|
# copyright (c) 2000-2003 ETH Zurich |
3 |
|
|
# see http://isg.ee.ethz.ch/tools/gedafe/ |
4 |
|
|
|
5 |
|
|
# released under the GNU General Public License |
6 |
|
|
|
7 |
|
|
package Gedafe::GUI; |
8 |
|
|
|
9 |
|
|
use strict; |
10 |
|
|
|
11 |
|
|
use Gedafe::Global qw(%g); |
12 |
|
|
use Gedafe::DB qw( |
13 |
|
|
DB_GetNumRecords |
14 |
|
|
DB_FetchList |
15 |
|
|
DB_GetRecord |
16 |
|
|
DB_AddRecord |
17 |
|
|
DB_UpdateRecord |
18 |
|
|
DB_GetCombo |
19 |
|
|
DB_DeleteRecord |
20 |
|
|
DB_GetDefault |
21 |
|
|
DB_ParseWidget |
22 |
|
|
DB_ID2HID |
23 |
|
|
DB_HID2ID |
24 |
|
|
DB_RawField |
25 |
|
|
DB_DumpTable |
26 |
|
|
); |
27 |
|
|
|
28 |
|
|
use Gedafe::Util qw( |
29 |
|
|
ConnectToTicketsDaemon |
30 |
|
|
MakeURL |
31 |
|
|
MyURL |
32 |
|
|
Template |
33 |
|
|
DropUnique |
34 |
|
|
UniqueFormStart |
35 |
|
|
FormStart |
36 |
|
|
UniqueFormEnd |
37 |
|
|
FormEnd |
38 |
|
|
NextRefresh |
39 |
|
|
); |
40 |
|
|
|
41 |
|
|
use POSIX; |
42 |
|
|
|
43 |
|
|
use vars qw(@ISA @EXPORT_OK); |
44 |
|
|
require Exporter; |
45 |
|
|
@ISA = qw(Exporter); |
46 |
|
|
@EXPORT_OK = qw( |
47 |
|
|
GUI_Entry |
48 |
|
|
GUI_List |
49 |
|
|
GUI_CheckFormID |
50 |
|
|
GUI_PostEdit |
51 |
|
|
GUI_Edit |
52 |
|
|
GUI_Delete |
53 |
|
|
GUI_Export |
54 |
|
|
GUI_DumpTable |
55 |
|
|
GUI_Pearl |
56 |
|
|
GUI_WidgetRead |
57 |
|
|
); |
58 |
|
|
|
59 |
|
|
sub GUI_AppletParam($$); |
60 |
|
|
sub GUI_CheckFormID($$); |
61 |
|
|
sub GUI_Delete($$$); |
62 |
|
|
sub GUI_DeleteLink($$$$); |
63 |
|
|
sub GUI_DumpTable($$$); |
64 |
|
|
sub GUI_Edit($$$); |
65 |
|
|
sub GUI_EditLink($$$$); |
66 |
|
|
sub GUI_Edit_Error($$$$$$); |
67 |
|
|
sub GUI_Entry($$$); |
68 |
|
|
sub GUI_Export($$$); |
69 |
|
|
sub GUI_ExportData($$); |
70 |
|
|
sub GUI_FilterFirst($$$$); |
71 |
|
|
sub GUI_Footer($); |
72 |
|
|
sub GUI_HTMLMarkup($); |
73 |
|
|
sub GUI_Hash2Str($); |
74 |
|
|
sub GUI_Header($$); |
75 |
|
|
sub GUI_InitTemplateArgs($$); |
76 |
|
|
sub GUI_List($$$); |
77 |
|
|
sub GUI_ListButtons($$$$); |
78 |
|
|
sub GUI_ListTable($$$); |
79 |
|
|
sub GUI_MakeCombo($$$$); |
80 |
|
|
sub GUI_MakeISearch($$$$$$); |
81 |
|
|
sub GUI_PostEdit($$$); |
82 |
|
|
sub GUI_Search($$$); |
83 |
|
|
sub GUI_Str2Hash($$); |
84 |
|
|
sub GUI_URL_Decode($); |
85 |
|
|
sub GUI_URL_Encode($); |
86 |
|
|
sub GUI_WidgetRead($$$); |
87 |
|
|
sub GUI_WidgetWrite($$$$); |
88 |
|
|
sub GUI_WidgetWrite_Date($$$); |
89 |
|
|
|
90 |
|
|
my %numeric_types = ( |
91 |
|
|
time => 1, |
92 |
|
|
timestamp => 1, |
93 |
|
|
int2 => 1, |
94 |
|
|
int4 => 1, |
95 |
|
|
int8 => 1, |
96 |
|
|
numeric => 1, |
97 |
|
|
float4 => 1, |
98 |
|
|
float8 => 1, |
99 |
|
|
); |
100 |
|
|
|
101 |
|
|
# setup for GUI_Export |
102 |
|
|
my ($csv, @exp_fmt_choices, %exp_fmt_choices); |
103 |
|
|
BEGIN { |
104 |
|
|
eval { |
105 |
|
|
# load modules necessary for formatting exported data: |
106 |
|
|
# if they don't load (aren't installed), no biggie- will fallback |
107 |
|
|
require Text::CSV_XS; |
108 |
|
|
$csv = Text::CSV_XS->new({binary => 1}); |
109 |
|
|
push(@exp_fmt_choices, 'csv'); |
110 |
|
|
$exp_fmt_choices{'csv'} = "Comma-separated (CSV)"; |
111 |
|
|
}; |
112 |
|
|
# add default (built-in) export format: tab-separated |
113 |
|
|
push(@exp_fmt_choices, 'tsv'); |
114 |
|
|
$exp_fmt_choices{'tsv'} = "Tab-separated (TSV)"; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
sub GUI_HTMLMarkup($) |
118 |
|
|
{ |
119 |
|
|
my $str = shift; |
120 |
|
|
|
121 |
|
|
# e-mail addresses |
122 |
|
|
my $emaddrchars = '\w.:/~-'; |
123 |
|
|
$str =~ s,([^\@$emaddrchars]|\A)([$emaddrchars]+\@(?:[\w-]+\.)+[\w-]+)([^\@$emaddrchars]|\Z),$1<A HREF="mailto:$2">$2</A>$3,gi; |
124 |
|
|
|
125 |
|
|
my $urlchars = '\w.:/?~%&=\@\#-'; |
126 |
|
|
|
127 |
|
|
# http addresses with explicit "http://" or "https://" |
128 |
|
|
$str =~ s,([^$urlchars]|\A)(https?://[$urlchars]+)([^$urlchars]|\Z),$1<A HREF="$2" TARGET="refwindow">$2</A>$3,gi; |
129 |
|
|
|
130 |
|
|
# http addresses beginning with "www." |
131 |
|
|
$str =~ s,([^$urlchars]|\A)(www\.[\w.:/?~%&=\#-]+)([^$urlchars]|\Z),$1<A HREF="http://$2" TARGET="refwindow">$2</A>$3,gi; |
132 |
|
|
|
133 |
|
|
# http addresses ending in a common top-level domain |
134 |
|
|
my $tlds = 'ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw|aero|biz|com|coop|info|museum|name|org|pro|gov|edu|mil|int'; |
135 |
|
|
|
136 |
|
|
$str =~ s,([^$urlchars]|\A)([\w.-]+\.)($tlds)(:\d+)?(/[\w./?~%&=\#-]*)?([^$urlchars]|\Z),$1<A HREF="http://$2$3$4$5" TARGET="refwindow">$2$3$4$5</A>$6,gi; |
137 |
|
|
|
138 |
|
|
return $str; |
139 |
|
|
} |
140 |
|
|
|
141 |
|
|
sub GUI_InitTemplateArgs($$) |
142 |
|
|
{ |
143 |
|
|
my ($s, $args) = @_; |
144 |
|
|
my $q = $s->{cgi}; |
145 |
|
|
|
146 |
|
|
my $refresh = NextRefresh(); |
147 |
|
|
|
148 |
|
|
$args->{DATABASE_DESC}=$g{db_database}{desc}; |
149 |
|
|
|
150 |
|
|
$args->{DOCUMENTATION_URL}=$g{conf}{documentation_url}; |
151 |
|
|
$args->{THEME}=$q->url_param('theme'); |
152 |
|
|
|
153 |
|
|
my $stripped_url = MakeURL($s->{url}, { |
154 |
|
|
filterfirst_button => '', |
155 |
|
|
search_button => '', |
156 |
|
|
}); |
157 |
|
|
$args->{BOOKMARK_URL}=MakeURL($stripped_url, { |
158 |
|
|
refresh => '', |
159 |
|
|
}); |
160 |
|
|
$args->{REFRESH_URL}=MakeURL($stripped_url, { |
161 |
|
|
refresh => $refresh, |
162 |
|
|
}); |
163 |
|
|
|
164 |
|
|
my $logout_url = MakeURL($stripped_url, { |
165 |
|
|
logout => 1, |
166 |
|
|
refresh => '', |
167 |
|
|
}); |
168 |
|
|
$args->{LOGOUT_URL}=$logout_url; |
169 |
|
|
|
170 |
|
|
my $entry_url = MakeURL($stripped_url, { |
171 |
|
|
id => '', |
172 |
|
|
action => '', |
173 |
|
|
orderby => '', |
174 |
|
|
table => '', |
175 |
|
|
offset => '', |
176 |
|
|
filterfirst => '', |
177 |
|
|
combo_filterfirst => '', |
178 |
|
|
descending => '', |
179 |
|
|
search_field => '', |
180 |
|
|
search_value => '', |
181 |
|
|
reedit_action => '', |
182 |
|
|
reedit_data => '', |
183 |
|
|
pearl=>'', |
184 |
|
|
}); |
185 |
|
|
$args->{ENTRY_URL}=$entry_url; |
186 |
|
|
$args->{REFRESH_ENTRY_URL}=MakeURL($entry_url, { |
187 |
|
|
refresh => $refresh, |
188 |
|
|
}); |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
sub GUI_Header($$) |
192 |
|
|
{ |
193 |
|
|
my ($s, $args) = @_; |
194 |
|
|
|
195 |
|
|
$args->{ELEMENT}='header'; |
196 |
|
|
print Template($args); |
197 |
|
|
|
198 |
|
|
$args->{ELEMENT}='header_table'; |
199 |
|
|
my $user = $args->{USER}; |
200 |
|
|
|
201 |
|
|
my $save_table = $args->{TABLE}; |
202 |
|
|
|
203 |
|
|
foreach my $t (@{$g{db_tables_list}}) { |
204 |
|
|
next if $g{db_tables}{$t}{hide}; |
205 |
|
|
next if $g{db_tables}{$t}{report}; |
206 |
|
|
if(defined $g{db_tables}{$t}{acls}{$user} and |
207 |
|
|
$g{db_tables}{$t}{acls}{$user} !~ /r/) { next; } |
208 |
|
|
my $desc = $g{db_tables}{$t}{desc}; |
209 |
|
|
$desc =~ s/ / /g; |
210 |
|
|
$args->{TABLE_TABLE}=$t; |
211 |
|
|
$args->{TABLE_DESC}=$desc; |
212 |
|
|
$args->{TABLE_URL}=MakeURL($args->{REFRESH_ENTRY_URL}, { |
213 |
|
|
action => 'list', |
214 |
|
|
table => $t, |
215 |
|
|
}); |
216 |
|
|
print Template($args); |
217 |
|
|
} |
218 |
|
|
delete $args->{TABLE_DESC}; |
219 |
|
|
delete $args->{TABLE_URL}; |
220 |
|
|
$args->{TABLE} = $save_table; |
221 |
|
|
|
222 |
|
|
$args->{ELEMENT}='header2'; |
223 |
|
|
print Template($args); |
224 |
|
|
|
225 |
|
|
delete $args->{ELEMENT}; |
226 |
|
|
|
227 |
|
|
$s->{header_sent}=1; |
228 |
|
|
} |
229 |
|
|
|
230 |
|
|
sub GUI_Footer($) |
231 |
|
|
{ |
232 |
|
|
my ($args) = @_; |
233 |
|
|
$args->{ELEMENT}='footer'; |
234 |
|
|
print Template($args); |
235 |
|
|
delete $args->{ELEMENT}; |
236 |
|
|
} |
237 |
|
|
|
238 |
|
|
|
239 |
|
|
sub GUI_Edit_Error($$$$$$) |
240 |
|
|
{ |
241 |
|
|
my ($s, $user, $str, $form_url, $data, $action) = @_; |
242 |
|
|
my $q = $s->{cgi}; |
243 |
|
|
|
244 |
|
|
my %template_args = ( |
245 |
|
|
PAGE => 'edit_error', |
246 |
|
|
USER => $user, |
247 |
|
|
TITLE => 'Database Error', |
248 |
|
|
ERROR => $str, |
249 |
|
|
REEDIT_URL => MakeURL($form_url, { |
250 |
|
|
action => 'reedit', |
251 |
|
|
reedit_action => $action, |
252 |
|
|
reedit_data => $data, |
253 |
|
|
}), |
254 |
|
|
); |
255 |
|
|
|
256 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
257 |
|
|
GUI_Header($s, \%template_args); |
258 |
|
|
|
259 |
|
|
$template_args{ELEMENT}='edit_error'; |
260 |
|
|
print Template(\%template_args); |
261 |
|
|
|
262 |
|
|
GUI_Footer(\%template_args); |
263 |
|
|
exit; |
264 |
|
|
} |
265 |
|
|
|
266 |
|
|
sub GUI_CheckFormID($$) |
267 |
|
|
{ |
268 |
|
|
my ($s, $user) = @_; |
269 |
|
|
my $q = $s->{cgi}; |
270 |
|
|
|
271 |
|
|
my $next_url = $q->param('next_url'); |
272 |
|
|
my %template_args = ( |
273 |
|
|
PAGE => 'doubleform', |
274 |
|
|
USER => $user, |
275 |
|
|
TITLE => "Duplicate Form", |
276 |
|
|
NEXT_URL => $next_url, |
277 |
|
|
); |
278 |
|
|
|
279 |
|
|
if(!DropUnique($s, $q->param('form_id'))) { |
280 |
|
|
print $q->header; |
281 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
282 |
|
|
GUI_Header($s, \%template_args); |
283 |
|
|
$template_args{ELEMENT}='doubleform'; |
284 |
|
|
print Template(\%template_args); |
285 |
|
|
GUI_Footer(\%template_args); |
286 |
|
|
exit; |
287 |
|
|
} |
288 |
|
|
} |
289 |
|
|
|
290 |
|
|
sub GUI_Entry($$$) |
291 |
|
|
{ |
292 |
|
|
my ($s, $user, $dbh) = @_; |
293 |
|
|
my $q = $s->{cgi}; |
294 |
|
|
|
295 |
|
|
my $refresh = NextRefresh(); |
296 |
|
|
|
297 |
|
|
my %template_args = ( |
298 |
|
|
USER => $user, |
299 |
|
|
TITLE => 'Entry', |
300 |
|
|
PAGE => 'entry', |
301 |
|
|
); |
302 |
|
|
|
303 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
304 |
|
|
GUI_Header($s, \%template_args); |
305 |
|
|
|
306 |
|
|
$template_args{ELEMENT}='tables_list_header', |
307 |
|
|
print Template(\%template_args); |
308 |
|
|
|
309 |
|
|
$template_args{ELEMENT}='entrytable'; |
310 |
|
|
foreach my $t (@{$g{db_tables_list}}) { |
311 |
|
|
next if $g{db_tables}{$t}{hide}; |
312 |
|
|
next if $g{db_tables}{$t}{report}; |
313 |
|
|
if(defined $g{db_tables}{$t}{acls}{$user} and |
314 |
|
|
$g{db_tables}{$t}{acls}{$user} !~ /r/) { next; } |
315 |
|
|
my $desc = $g{db_tables}{$t}{desc}; |
316 |
|
|
$desc =~ s/ / /g; |
317 |
|
|
$template_args{TABLE_DESC}=$desc; |
318 |
|
|
$template_args{TABLE_URL}= MakeURL($s->{url}, { |
319 |
|
|
action => 'list', |
320 |
|
|
table => $t, |
321 |
|
|
refresh => $refresh, |
322 |
|
|
}); |
323 |
|
|
print Template(\%template_args); |
324 |
|
|
} |
325 |
|
|
delete $template_args{TABLE_DESC}; |
326 |
|
|
delete $template_args{TABLE_URL}; |
327 |
|
|
|
328 |
|
|
$template_args{ELEMENT}='reports_list_header'; |
329 |
|
|
print Template(\%template_args); |
330 |
|
|
|
331 |
|
|
$template_args{ELEMENT}='entrytable'; |
332 |
|
|
foreach my $t (@{$g{db_tables_list}}) { |
333 |
|
|
next if $g{db_tables}{$t}{hide}; |
334 |
|
|
next unless $g{db_tables}{$t}{report}; |
335 |
|
|
if(defined $g{db_tables}{$t}{acls}{$user} and |
336 |
|
|
$g{db_tables}{$t}{acls}{$user} !~ /r/) { next; } |
337 |
|
|
my $desc = $g{db_tables}{$t}{desc}; |
338 |
|
|
$desc =~ s/ / /g; |
339 |
|
|
$template_args{TABLE_DESC}=$desc; |
340 |
|
|
$template_args{TABLE_URL}= MakeURL($s->{url}, { |
341 |
|
|
action => 'list', |
342 |
|
|
table => $t, |
343 |
|
|
refresh => $refresh, |
344 |
|
|
}); |
345 |
|
|
$template_args{REPORT}=1; |
346 |
|
|
print Template(\%template_args); |
347 |
|
|
} |
348 |
|
|
|
349 |
|
|
if(defined $g{pearls} and scalar %{$g{pearls}}) { |
350 |
|
|
$template_args{ELEMENT}='pearls_list_header'; |
351 |
|
|
print Template(\%template_args); |
352 |
|
|
|
353 |
|
|
$template_args{ELEMENT}='entrytable'; |
354 |
|
|
foreach my $t (sort {$a cmp $b} keys %{$g{pearls}}) { |
355 |
|
|
if (ref $g{pearls}{$t}) { |
356 |
|
|
@template_args{qw(TABLE_DESC TABLE_INFO)}=($g{pearls}{$t}->info); |
357 |
|
|
$template_args{TABLE_URL}= MakeURL($s->{url}, { |
358 |
|
|
action => 'configpearl', |
359 |
|
|
pearl=> $t, |
360 |
|
|
table => undef, |
361 |
|
|
refresh => $refresh, |
362 |
|
|
}); |
363 |
|
|
} else { |
364 |
|
|
$template_args{REPORT}=1; |
365 |
|
|
@template_args{qw(TABLE_DESC TABLE_INFO)}=($t,$g{pearls}{$t}); |
366 |
|
|
$template_args{TABLE_URL}= MakeURL($s->{url}, { |
367 |
|
|
action => 'entry', |
368 |
|
|
pearl=> $t, |
369 |
|
|
table => undef, |
370 |
|
|
refresh => $refresh, |
371 |
|
|
}); |
372 |
|
|
$template_args{REPORT}=1; |
373 |
|
|
} |
374 |
|
|
print Template(\%template_args); |
375 |
|
|
} |
376 |
|
|
} |
377 |
|
|
|
378 |
|
|
GUI_Footer(\%template_args); |
379 |
|
|
} |
380 |
|
|
|
381 |
|
|
sub GUI_FilterFirst($$$$) |
382 |
|
|
{ |
383 |
|
|
my $s = shift; |
384 |
|
|
my $q = $s->{cgi}; |
385 |
|
|
my $dbh = shift; |
386 |
|
|
my $view = shift; |
387 |
|
|
my $template_args = shift; |
388 |
|
|
my $myurl = MyURL($q); |
389 |
|
|
my $ff_field = $g{db_tables}{$view}{meta}{filterfirst}; |
390 |
|
|
my $ff_value = $q->url_param('filterfirst') || |
391 |
|
|
$q->url_param('combo_filterfirst') || ''; |
392 |
|
|
|
393 |
|
|
defined $ff_field or return undef; |
394 |
|
|
|
395 |
|
|
my $ff_ref = $g{db_fields}{$view}{$ff_field}{reference}; |
396 |
|
|
my $ff_combo_name = "${ff_ref}_combo" unless not defined $ff_ref; |
397 |
|
|
|
398 |
|
|
if(!defined $ff_ref or !defined $g{db_tables}{$ff_combo_name}) { |
399 |
|
|
die "combo not found for $ff_field (reference: ${ff_ref})"; |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
my $ff_combo = GUI_MakeCombo($dbh, $ff_combo_name, "combo_filterfirst", $ff_value); |
403 |
|
|
|
404 |
|
|
# ID->HID: if referenced table has a hid, assume the hid is shown in |
405 |
|
|
# this view and search that instead. In Gedafe 1.0 mode, the |
406 |
|
|
# combo-boxes always referenced the hid, so it is already done |
407 |
|
|
if($g{conf}{gedafe_compat} ne '1.0') { |
408 |
|
|
if(defined $g{db_fields}{$ff_ref}{"${ff_ref}_hid"}) { |
409 |
|
|
$ff_value = DB_ID2HID($dbh,$ff_ref,$ff_value); |
410 |
|
|
} |
411 |
|
|
} |
412 |
|
|
|
413 |
|
|
my $ff_hidden = ''; |
414 |
|
|
foreach($q->url_param) { |
415 |
|
|
next if /^filterfirst/; |
416 |
|
|
next if /button$/; |
417 |
|
|
$ff_hidden .= "<INPUT TYPE=\"hidden\" NAME=\"$_\" VALUE=\"".$q->url_param($_)."\">\n"; |
418 |
|
|
} |
419 |
|
|
$template_args->{ELEMENT}='filterfirst'; |
420 |
|
|
$template_args->{FILTERFIRST_FIELD}=$ff_field; |
421 |
|
|
$template_args->{FILTERFIRST_FIELD_DESC}=$g{db_fields}{$view}{$ff_field}{desc}; |
422 |
|
|
$template_args->{FILTERFIRST_COMBO}=$ff_combo; |
423 |
|
|
$template_args->{FILTERFIRST_HIDDEN}=$ff_hidden; |
424 |
|
|
$template_args->{FILTERFIRST_ACTION}=$q->url; |
425 |
|
|
print Template($template_args); |
426 |
|
|
delete $template_args->{ELEMENT}; |
427 |
|
|
delete $template_args->{FILTERFIRST_FIELD}; |
428 |
|
|
delete $template_args->{FILTERFIRST_FIELD_DESC}; |
429 |
|
|
delete $template_args->{FILTERFIRST_COMBO}; |
430 |
|
|
delete $template_args->{FILTERFIRST_HIDDEN}; |
431 |
|
|
delete $template_args->{FILTERFIRST_ACTION}; |
432 |
|
|
|
433 |
|
|
if($ff_value eq '') { $ff_value = undef; } |
434 |
|
|
|
435 |
|
|
return ($ff_field, $ff_value); |
436 |
|
|
} |
437 |
|
|
|
438 |
|
|
sub GUI_Search($$$) |
439 |
|
|
{ |
440 |
|
|
my $s = shift; |
441 |
|
|
my $q = $s->{cgi}; |
442 |
|
|
my $view = shift; |
443 |
|
|
my $template_args = shift; |
444 |
|
|
my $search_field = $q->url_param('search_field') || ''; |
445 |
|
|
my $search_value = $q->url_param('search_value') || ''; |
446 |
|
|
|
447 |
|
|
$search_field =~ s/^\s*//; $search_field =~ s/\s*$//; |
448 |
|
|
$search_value =~ s/^\s*//; $search_value =~ s/\s*$//; |
449 |
|
|
my $fields = $g{db_fields}{$view}; |
450 |
|
|
my $search_combo = "<SELECT name=\"search_field\" SIZE=\"1\">\n"; |
451 |
|
|
foreach(@{$g{db_fields_list}{$view}}) { |
452 |
|
|
next if /${view}_id/; |
453 |
|
|
if(/^$search_field$/) { |
454 |
|
|
$search_combo .= "<OPTION SELECTED VALUE=\"$_\">$fields->{$_}{desc}</OPTION>\n"; |
455 |
|
|
} |
456 |
|
|
else { |
457 |
|
|
$search_combo .= "<OPTION VALUE=\"$_\">$fields->{$_}{desc}</OPTION>\n"; |
458 |
|
|
} |
459 |
|
|
} |
460 |
|
|
$search_combo .= "</SELECT>\n"; |
461 |
|
|
my $search_hidden = ''; |
462 |
|
|
foreach($q->url_param) { |
463 |
|
|
next if /^search/; |
464 |
|
|
next if /^button/; |
465 |
|
|
next if /^offset$/; |
466 |
|
|
$search_hidden .= "<INPUT TYPE=\"hidden\" NAME=\"$_\" VALUE=\"".$q->url_param($_)."\">\n"; |
467 |
|
|
} |
468 |
|
|
$template_args->{ELEMENT} = 'search'; |
469 |
|
|
$template_args->{SEARCH_ACTION} = $q->url; |
470 |
|
|
$template_args->{SEARCH_COMBO} = $search_combo; |
471 |
|
|
$template_args->{SEARCH_HIDDEN} = $search_hidden; |
472 |
|
|
$template_args->{SEARCH_VALUE} = $search_value; |
473 |
|
|
$template_args->{SEARCH_SHOWALL} = MakeURL(MyURL($q), { search_value=>'', search_button=>'', search_field=>'' }); |
474 |
|
|
print Template($template_args); |
475 |
|
|
delete $template_args->{ELEMENT}; |
476 |
|
|
delete $template_args->{SEARCH_ACTION}; |
477 |
|
|
delete $template_args->{SEARCH_COMBO}; |
478 |
|
|
delete $template_args->{SEARCH_HIDDEN}; |
479 |
|
|
delete $template_args->{SEARCH_VALUE}; |
480 |
|
|
delete $template_args->{SEARCH_SHOWALL}; |
481 |
|
|
|
482 |
|
|
# search date = TODAY |
483 |
|
|
if($search_field ne '') { |
484 |
|
|
if($g{db_fields}{$view}{$search_field}{type} eq 'date') { |
485 |
|
|
if($search_value =~ /^today$/i) { |
486 |
|
|
$search_value = POSIX::strftime("%Y-%m-%d", localtime); |
487 |
|
|
} |
488 |
|
|
elsif($search_value =~ /^yesterday$/i) { |
489 |
|
|
my $time = time; |
490 |
|
|
$time -= 3600 * 24; |
491 |
|
|
$search_value = POSIX::strftime("%Y-%m-%d", localtime($time)); |
492 |
|
|
} |
493 |
|
|
} |
494 |
|
|
} |
495 |
|
|
|
496 |
|
|
return ($search_field, $search_value); |
497 |
|
|
} |
498 |
|
|
|
499 |
|
|
sub GUI_EditLink($$$$) |
500 |
|
|
{ |
501 |
|
|
my ($s, $template_args, $list, $row) = @_; |
502 |
|
|
my $edit_url; |
503 |
|
|
$edit_url = MakeURL($s->{url}, { |
504 |
|
|
action=>'edit', |
505 |
|
|
id=>$row->[0], |
506 |
|
|
refresh=>NextRefresh, |
507 |
|
|
}); |
508 |
|
|
$template_args->{ELEMENT}='td_edit'; |
509 |
|
|
$template_args->{EDIT_URL}=$edit_url; |
510 |
|
|
print Template($template_args); |
511 |
|
|
delete $template_args->{EDIT_URL}; |
512 |
|
|
} |
513 |
|
|
|
514 |
|
|
sub GUI_DeleteLink($$$$) |
515 |
|
|
{ |
516 |
|
|
my ($s, $template_args, $list, $row) = @_; |
517 |
|
|
my $delete_url; |
518 |
|
|
$delete_url = MakeURL($s->{url}, { |
519 |
|
|
action=>'delete', |
520 |
|
|
id=>$row->[0], |
521 |
|
|
refresh=>NextRefresh, |
522 |
|
|
}); |
523 |
|
|
$template_args->{ELEMENT}='td_delete'; |
524 |
|
|
$template_args->{DELETE_URL}=$delete_url; |
525 |
|
|
print Template($template_args); |
526 |
|
|
delete $template_args->{DELETE_URL}; |
527 |
|
|
} |
528 |
|
|
|
529 |
|
|
sub GUI_ListTable($$$) |
530 |
|
|
{ |
531 |
|
|
my ($s, $list, $page) = @_; |
532 |
|
|
|
533 |
|
|
# user can edit only if they have sql UPDATE privilege, and |
534 |
|
|
# this table is a real table, not a report (view) |
535 |
|
|
my $can_edit = ($list->{acl} =~ /w/ and !$list->{is_report}); |
536 |
|
|
my $can_delete = $can_edit; |
537 |
|
|
|
538 |
|
|
my %template_args = ( |
539 |
|
|
USER => $s->{user}, |
540 |
|
|
PAGE => $page, |
541 |
|
|
URL => $s->{url}, |
542 |
|
|
TABLE => $list->{spec}{view}, |
543 |
|
|
TITLE => "$g{db_tables}{$list->{spec}{table}}{desc}", |
544 |
|
|
ORDERBY => $list->{spec}{orderby}, |
545 |
|
|
); |
546 |
|
|
|
547 |
|
|
# <TABLE> |
548 |
|
|
$template_args{ELEMENT}='table'; |
549 |
|
|
|
550 |
|
|
# total number of records in result set |
551 |
|
|
$template_args{NUM_RECORDS} = $list->{totalrecords} |
552 |
|
|
if $g{conf}{show_row_count}; |
553 |
|
|
|
554 |
|
|
print Template(\%template_args); |
555 |
|
|
$s->{in_table}=1; # die will put a </TABLE> |
556 |
|
|
|
557 |
|
|
# header |
558 |
|
|
$template_args{ELEMENT}='tr'; |
559 |
|
|
print Template(\%template_args); |
560 |
|
|
for my $c (@{$list->{columns}}) { |
561 |
|
|
next if $c->{hide_list}; |
562 |
|
|
my $sort_url; |
563 |
|
|
if($list->{spec}{orderby} eq $c->{field}) { |
564 |
|
|
my $d = $list->{spec}{descending} ? '' : 1; |
565 |
|
|
$sort_url = MakeURL($s->{url}, { descending => $d }); |
566 |
|
|
} |
567 |
|
|
else { |
568 |
|
|
$sort_url = MakeURL($s->{url}, { orderby => "$c->{field}", descending=>'' }); |
569 |
|
|
} |
570 |
|
|
|
571 |
|
|
$template_args{ELEMENT}='th'; |
572 |
|
|
$template_args{DATA}=$c->{desc}; |
573 |
|
|
$template_args{FIELD}=$c->{field}; |
574 |
|
|
$template_args{SORT_URL}=$sort_url; |
575 |
|
|
print Template(\%template_args); |
576 |
|
|
} |
577 |
|
|
delete $template_args{DATA}; |
578 |
|
|
delete $template_args{FIELD}; |
579 |
|
|
delete $template_args{SORT_URL}; |
580 |
|
|
if($can_edit) { |
581 |
|
|
$template_args{ELEMENT}='th_edit'; |
582 |
|
|
print Template(\%template_args); |
583 |
|
|
} |
584 |
|
|
if($can_delete) { |
585 |
|
|
$template_args{ELEMENT}='th_delete'; |
586 |
|
|
print Template(\%template_args); |
587 |
|
|
} |
588 |
|
|
$template_args{ELEMENT}='xtr'; |
589 |
|
|
print Template(\%template_args); |
590 |
|
|
|
591 |
|
|
# data |
592 |
|
|
$list->{displayed_recs} = 0; |
593 |
|
|
for my $row (@{$list->{data}}) { |
594 |
|
|
$list->{displayed_recs}++; |
595 |
|
|
if($list->{displayed_recs}%2) { $template_args{EVENROW}=1; } |
596 |
|
|
else { $template_args{ODDROW}=1; } |
597 |
|
|
|
598 |
|
|
$template_args{ELEMENT}='tr'; |
599 |
|
|
print Template(\%template_args); |
600 |
|
|
my $column_number = 0; |
601 |
|
|
for my $d (@{$row->[1]}) { |
602 |
|
|
my $c = $list->{columns}[$column_number]; |
603 |
|
|
$column_number++; |
604 |
|
|
next if $c->{hide_list}; |
605 |
|
|
if($c->{type} eq 'bytea' && $d ne ' '){ |
606 |
|
|
my $bloburl = MakeURL($s->{url}, { |
607 |
|
|
table => $list->{spec}{view}, |
608 |
|
|
action => 'dumpblob', |
609 |
|
|
id => $row->[0], |
610 |
|
|
field => $c->{field}, |
611 |
|
|
}); |
612 |
|
|
$d = qq{<A HREF="$bloburl" TARGET="_blank">$d</A>}; |
613 |
|
|
} |
614 |
|
|
my $align = $c->{align}; |
615 |
|
|
defined $align or $align = $numeric_types{$c->{type}} ? |
616 |
|
|
'"RIGHT" NOWRAP' : '"LEFT"' unless defined $align; |
617 |
|
|
$template_args{ALIGN}=$align; |
618 |
|
|
$template_args{ELEMENT}='td'; |
619 |
|
|
$template_args{DATA}=$d; |
620 |
|
|
$template_args{MARKUP}=GUI_HTMLMarkup($d) if $d and $c->{markup}; |
621 |
|
|
print Template(\%template_args); |
622 |
|
|
} |
623 |
|
|
delete $template_args{DATA}; |
624 |
|
|
delete $template_args{ALIGN}; |
625 |
|
|
delete $template_args{MARKUP}; |
626 |
|
|
|
627 |
|
|
$template_args{ID} = $row->[0]; |
628 |
|
|
GUI_EditLink($s, \%template_args, $list, $row) if $can_edit; |
629 |
|
|
GUI_DeleteLink($s, \%template_args, $list, $row) if $can_delete; |
630 |
|
|
delete $template_args{ID}; |
631 |
|
|
|
632 |
|
|
$template_args{ELEMENT}='xtr'; |
633 |
|
|
print Template(\%template_args); |
634 |
|
|
|
635 |
|
|
if($list->{displayed_recs}%2) {delete $template_args{EVENROW};} |
636 |
|
|
else {delete $template_args{ODDROW};} |
637 |
|
|
} |
638 |
|
|
|
639 |
|
|
# </TABLE> |
640 |
|
|
$template_args{ELEMENT}='xtable'; |
641 |
|
|
print Template(\%template_args); |
642 |
|
|
$s->{in_table}=0; |
643 |
|
|
} |
644 |
|
|
|
645 |
|
|
sub GUI_ListButtons($$$$) |
646 |
|
|
{ |
647 |
|
|
my ($s, $list, $page, $position) = @_; |
648 |
|
|
|
649 |
|
|
my %template_args = ( |
650 |
|
|
USER => $s->{user}, |
651 |
|
|
PAGE => $page, |
652 |
|
|
URL => $s->{url}, |
653 |
|
|
TABLE => $list->{spec}{view}, |
654 |
|
|
TITLE => "$g{db_tables}{$list->{spec}{table}}{desc}", |
655 |
|
|
TOP => $position eq 'top', |
656 |
|
|
BOTTOM => $position eq 'bottom', |
657 |
|
|
IS_REPORT => $list->{is_report} |
658 |
|
|
); |
659 |
|
|
|
660 |
|
|
my $next_refresh = NextRefresh; |
661 |
|
|
|
662 |
|
|
my $nextoffset = $list->{spec}{offset}+$list->{spec}{limit}; |
663 |
|
|
my $prevoffset = $list->{spec}{offset}-$list->{spec}{limit}; |
664 |
|
|
$prevoffset > 0 or $prevoffset = ''; |
665 |
|
|
|
666 |
|
|
my $can_add = ($list->{acl} =~ /a/); |
667 |
|
|
my $add_url = $can_add ? MakeURL($s->{url}, { |
668 |
|
|
action => 'add', |
669 |
|
|
refresh => $next_refresh, |
670 |
|
|
}) : undef; |
671 |
|
|
|
672 |
|
|
my $prev_url = $list->{spec}{offset} != 0 ? MakeURL($s->{url}, |
673 |
|
|
{ offset => $prevoffset }) : undef; |
674 |
|
|
my $next_url = $list->{end} ? undef : |
675 |
|
|
MakeURL($s->{url}, { offset => $nextoffset }); |
676 |
|
|
|
677 |
|
|
$template_args{ELEMENT}='buttons'; |
678 |
|
|
$template_args{ADD_URL}=$add_url; |
679 |
|
|
$template_args{PREV_URL}=$prev_url; |
680 |
|
|
$template_args{NEXT_URL}=$next_url; |
681 |
|
|
|
682 |
|
|
# calculate correct offset for last page of results |
683 |
|
|
if ($g{conf}{show_row_count}) { |
684 |
|
|
my $totalrecs = $template_args{NUM_RECORDS} = $list->{totalrecords}; |
685 |
|
|
my $lastoffset = |
686 |
|
|
($totalrecs % $list->{spec}{limit} == 0 |
687 |
|
|
? $totalrecs - $list->{spec}{limit} |
688 |
|
|
: $totalrecs - ($totalrecs % $list->{spec}{limit})); |
689 |
|
|
my $first_url = |
690 |
|
|
($prev_url && $prevoffset ne '' |
691 |
|
|
? MakeURL($s->{url}, { offset => '' }) : undef); |
692 |
|
|
my $last_url = |
693 |
|
|
($next_url && $nextoffset != $lastoffset |
694 |
|
|
? MakeURL($s->{url}, { offset => $lastoffset }) : undef); |
695 |
|
|
$template_args{START_RECNUM}= |
696 |
|
|
($list->{spec}{offset}+1 > $totalrecs |
697 |
|
|
? $totalrecs |
698 |
|
|
: $list->{spec}{offset}+1); |
699 |
|
|
$template_args{END_RECNUM}= |
700 |
|
|
($list->{spec}{offset}+$#{$list->{data}}+1 > $totalrecs |
701 |
|
|
? $totalrecs |
702 |
|
|
: $list->{spec}{offset}+$#{$list->{data}}+1); |
703 |
|
|
$template_args{FIRST_URL}=$first_url; |
704 |
|
|
$template_args{LAST_URL}=$last_url; |
705 |
|
|
} |
706 |
|
|
|
707 |
|
|
print Template(\%template_args); |
708 |
|
|
} |
709 |
|
|
|
710 |
|
|
sub GUI_List($$$) |
711 |
|
|
{ |
712 |
|
|
my ($s, $user, $dbh) = @_; |
713 |
|
|
my $q = $s->{cgi}; |
714 |
|
|
my $table = $q->url_param('table'); |
715 |
|
|
|
716 |
|
|
my %template_args = ( |
717 |
|
|
USER => $user, |
718 |
|
|
PAGE => 'list', |
719 |
|
|
URL => $s->{url}, |
720 |
|
|
TABLE => $table, |
721 |
|
|
TITLE => "$g{db_tables}{$table}{desc}", |
722 |
|
|
EXPORT_AS_CHOICE => $#exp_fmt_choices > 0, |
723 |
|
|
EXPORT_CHOICES => "<SELECT NAME=\"export_format\">\n".join("\n", map { "<OPTION VALUE=\"$_\">$exp_fmt_choices{$_}</OPTION>" } @exp_fmt_choices).'</SELECT>', |
724 |
|
|
EXPORT_URL => MakeURL(MyURL($q), { action => 'export' }), |
725 |
|
|
); |
726 |
|
|
|
727 |
|
|
# header |
728 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
729 |
|
|
GUI_Header($s, \%template_args); |
730 |
|
|
|
731 |
|
|
# build list-spec |
732 |
|
|
my %spec = ( |
733 |
|
|
table => $table, |
734 |
|
|
view => defined $g{db_tables}{"${table}_list"} ? |
735 |
|
|
"${table}_list" : $table, |
736 |
|
|
offset => $q->url_param('offset') || 0, |
737 |
|
|
limit => $q->url_param('list_rows') || $g{conf}{list_rows}, |
738 |
|
|
orderby => $q->url_param('orderby') || '', |
739 |
|
|
descending => $q->url_param('descending') || 0, |
740 |
|
|
); |
741 |
|
|
|
742 |
|
|
# filterfirst |
743 |
|
|
($spec{filter_field}, $spec{filter_value}) = |
744 |
|
|
GUI_FilterFirst($s, $dbh, $spec{view}, \%template_args); |
745 |
|
|
|
746 |
|
|
# search |
747 |
|
|
($spec{search_field}, $spec{search_value}) = |
748 |
|
|
GUI_Search($s, $spec{view}, \%template_args); |
749 |
|
|
|
750 |
|
|
# fetch list |
751 |
|
|
my $list = DB_FetchList($s, \%spec); |
752 |
|
|
|
753 |
|
|
# get total number of records for this search set |
754 |
|
|
$list->{totalrecords} = DB_GetNumRecords($s, \%spec) |
755 |
|
|
if $g{conf}{show_row_count}; |
756 |
|
|
|
757 |
|
|
# is it a report (read-only)? |
758 |
|
|
$list->{is_report} = 1 if $g{db_tables}{$table}{report}; |
759 |
|
|
|
760 |
|
|
my $list_buttons = $g{conf}{list_buttons} || 'both'; |
761 |
|
|
|
762 |
|
|
# top buttons |
763 |
|
|
if($list_buttons eq 'top' or $list_buttons eq 'both'){ |
764 |
|
|
GUI_ListButtons($s, $list, 'list', 'top'); |
765 |
|
|
} |
766 |
|
|
|
767 |
|
|
# display table |
768 |
|
|
GUI_ListTable($s, $list, 'list'); |
769 |
|
|
|
770 |
|
|
# bottom buttons |
771 |
|
|
if($list_buttons eq 'bottom' or $list_buttons eq 'both'){ |
772 |
|
|
GUI_ListButtons($s, $list, 'list', 'bottom'); |
773 |
|
|
} |
774 |
|
|
delete $list->{displayed_recs}; |
775 |
|
|
delete $list->{totalrecords} if $g{conf}{show_row_count}; |
776 |
|
|
|
777 |
|
|
# footer |
778 |
|
|
GUI_Footer(\%template_args); |
779 |
|
|
} |
780 |
|
|
|
781 |
|
|
sub GUI_ExportData($$) |
782 |
|
|
{ |
783 |
|
|
my ($s, $list) = @_; |
784 |
|
|
my $q = $s->{cgi}; |
785 |
|
|
|
786 |
|
|
# decide what export format to use: 'csv' only if Text::CSV_XS loaded |
787 |
|
|
my $exp_fmt = ref $csv && $q->param('export_format') eq 'csv' ? 'csv' : 'tsv'; |
788 |
|
|
|
789 |
|
|
# print HTTP Content-type header |
790 |
|
|
if ($exp_fmt eq 'csv') { |
791 |
|
|
print $q->header(-type=>'text/csv', |
792 |
|
|
-attachment=>$list->{spec}{table}.'.csv', |
793 |
|
|
-expires=>'-1d'); |
794 |
|
|
} else { |
795 |
|
|
print $q->header(-type=>'text/tab-separated-values', |
796 |
|
|
-attachment=>$list->{spec}{table}.'.tsv', |
797 |
|
|
-expires=>'-1d'); |
798 |
|
|
} |
799 |
|
|
|
800 |
|
|
# fields |
801 |
|
|
my $fields = $g{db_fields}{$list->{spec}{view}}; |
802 |
|
|
if ($exp_fmt eq 'csv') { |
803 |
|
|
my $status = $csv->combine(map {$fields->{$_}{desc}} @{$list->{fields}}); |
804 |
|
|
print $csv->string(). "\n"; |
805 |
|
|
} else { |
806 |
|
|
print join("\t", map {$fields->{$_}{desc}} @{$list->{fields}})."\n"; |
807 |
|
|
} |
808 |
|
|
|
809 |
|
|
# data |
810 |
|
|
for my $row (@{$list->{data}}) { |
811 |
|
|
# if correct module is loaded and user selected 'CSV' |
812 |
|
|
if ($exp_fmt eq 'csv') { |
813 |
|
|
my $status = $csv->combine(@{$row->[1]}); |
814 |
|
|
print $csv->string() . "\n"; |
815 |
|
|
} else { |
816 |
|
|
print join("\t", map { |
817 |
|
|
my $str = defined $_ ? $_ : ''; |
818 |
|
|
$str=~s/\t/ /g; |
819 |
|
|
$str=~s/\n/\r/g; |
820 |
|
|
$str; |
821 |
|
|
} @{$row->[1]})."\n"; |
822 |
|
|
} |
823 |
|
|
} |
824 |
|
|
} |
825 |
|
|
|
826 |
|
|
sub GUI_Export($$$) |
827 |
|
|
{ |
828 |
|
|
my ($s, $user, $dbh) = @_; |
829 |
|
|
my $q = $s->{cgi}; |
830 |
|
|
my $table = $q->url_param('table'); |
831 |
|
|
|
832 |
|
|
my %template_args = ( |
833 |
|
|
USER => $user, |
834 |
|
|
PAGE => 'export', |
835 |
|
|
URL => $s->{url}, |
836 |
|
|
TABLE => $table, |
837 |
|
|
TITLE => "$g{db_tables}{$table}{desc}", |
838 |
|
|
); |
839 |
|
|
|
840 |
|
|
# build list-spec |
841 |
|
|
my %spec = ( |
842 |
|
|
table => $table, |
843 |
|
|
view => defined $g{db_tables}{"${table}_list"} ? |
844 |
|
|
"${table}_list" : $table, |
845 |
|
|
orderby => $q->url_param('orderby') || '', |
846 |
|
|
descending => $q->url_param('descending') || 0, |
847 |
|
|
export => 1, |
848 |
|
|
); |
849 |
|
|
|
850 |
|
|
# get search params |
851 |
|
|
$spec{search_field} = $q->url_param('search_field') || ''; |
852 |
|
|
$spec{search_value} = $q->url_param('search_value') || ''; |
853 |
|
|
$spec{search_field} =~ s/^\s*//; $spec{search_field} =~ s/\s*$//; |
854 |
|
|
$spec{search_value} =~ s/^\s*//; $spec{search_value} =~ s/\s*$//; |
855 |
|
|
|
856 |
|
|
# fetch list |
857 |
|
|
my $list = DB_FetchList($s, \%spec); |
858 |
|
|
|
859 |
|
|
GUI_ExportData($s, $list); |
860 |
|
|
} |
861 |
|
|
|
862 |
|
|
# CGI.pm already encodes/decodes parameters, but we want to do it ourselves |
863 |
|
|
# since we need to differentiate for example in reedit_data between a comma |
864 |
|
|
# as value and a comma as separator. Therefore we use the escape '!' instead |
865 |
|
|
# of '%'. |
866 |
|
|
sub GUI_URL_Encode($) |
867 |
|
|
{ |
868 |
|
|
my ($str) = @_; |
869 |
|
|
defined $str or $str = ''; |
870 |
|
|
$str =~ s/!/gedafe_PROTECTED_eXclamatiOn/g; |
871 |
|
|
$str =~ s/\W/'!'.sprintf('%2X',ord($&))/eg; |
872 |
|
|
$str =~ s/gedafe_PROTECTED_eXclamatiOn/'!'.sprintf('%2X',ord('!'))/eg; |
873 |
|
|
return $str; |
874 |
|
|
} |
875 |
|
|
|
876 |
|
|
sub GUI_URL_Decode($) |
877 |
|
|
{ |
878 |
|
|
my ($str) = @_; |
879 |
|
|
$str =~ s/!([0-9a-fA-F]{2})/pack("c",hex($1))/ge; |
880 |
|
|
return $str; |
881 |
|
|
} |
882 |
|
|
|
883 |
|
|
sub GUI_Hash2Str($) |
884 |
|
|
{ |
885 |
|
|
my ($record) = @_; |
886 |
|
|
my @data = (); |
887 |
|
|
for my $f (keys %$record) { |
888 |
|
|
my $d = GUI_URL_Encode($record->{$f}); |
889 |
|
|
push @data, "$f:$d"; |
890 |
|
|
} |
891 |
|
|
return join(',', @data); |
892 |
|
|
} |
893 |
|
|
|
894 |
|
|
sub GUI_Str2Hash($$) |
895 |
|
|
{ |
896 |
|
|
my ($str, $hash) = @_; |
897 |
|
|
for my $s (split(/,/, $str)) { |
898 |
|
|
if($s =~ /^(.*?):(.*)$/) { |
899 |
|
|
$hash->{$1} = GUI_URL_Decode($2); |
900 |
|
|
} |
901 |
|
|
} |
902 |
|
|
} |
903 |
|
|
|
904 |
|
|
sub GUI_WidgetRead($$$) |
905 |
|
|
{ |
906 |
|
|
my ($s, $input_name, $widget) = @_; |
907 |
|
|
my $q = $s->{cgi}; |
908 |
|
|
my $dbh = $s->{dbh}; |
909 |
|
|
|
910 |
|
|
my ($w, $warg) = DB_ParseWidget($widget); |
911 |
|
|
|
912 |
|
|
my $value = $q->param($input_name); |
913 |
|
|
|
914 |
|
|
if($w eq 'file'){ |
915 |
|
|
my $file = $value; |
916 |
|
|
my $deletefile = $q->param("file_delete_$input_name"); |
917 |
|
|
if($deletefile) { |
918 |
|
|
$value=""; |
919 |
|
|
} |
920 |
|
|
else { |
921 |
|
|
if($file) { |
922 |
|
|
my $filename = scalar $file; |
923 |
|
|
$filename =~ s/ /_/g; |
924 |
|
|
$filename =~ /([\w\d\.]+$)/; |
925 |
|
|
$filename = $1; |
926 |
|
|
my $mimetype = $q->uploadInfo($file)->{'Content-Type'}; |
927 |
|
|
my $blob=$filename.' '.$mimetype.'#'; |
928 |
|
|
my $buffer; |
929 |
|
|
while(read($file,$buffer,1024)){ |
930 |
|
|
$blob .=$buffer; |
931 |
|
|
} |
932 |
|
|
#note that value is set to a reference to the large blob |
933 |
|
|
$value=\$blob; |
934 |
|
|
} |
935 |
|
|
else { |
936 |
|
|
#when we are here the file field has not been set |
937 |
|
|
$value = undef; |
938 |
|
|
} |
939 |
|
|
} |
940 |
|
|
} |
941 |
|
|
if($w eq 'hid' or $w eq 'hidcombo' or $w eq 'hidisearch') { |
942 |
|
|
if(defined $value and $value !~ /^\s*$/) { |
943 |
|
|
$value=DB_HID2ID($dbh,$warg->{'ref'},$value); |
944 |
|
|
} |
945 |
|
|
} |
946 |
|
|
# if it's a combo and no value was specified in the text field... |
947 |
|
|
if($w eq 'idcombo' or $w eq 'hidcombo' or $w eq 'combo') { |
948 |
|
|
if(not defined $value or $value =~ /^\s*$/) { |
949 |
|
|
$value = $q->param("${input_name}_combo"); |
950 |
|
|
if($w eq 'hidcombo' and $g{conf}{gedafe_compat} eq '1.0') |
951 |
|
|
{ |
952 |
|
|
# hidcombos in 1.0 had to put the HID as key... |
953 |
|
|
$value = DB_HID2ID($dbh,$warg->{'ref'},$value); |
954 |
|
|
} |
955 |
|
|
} |
956 |
|
|
} |
957 |
|
|
|
958 |
|
|
return $value; |
959 |
|
|
} |
960 |
|
|
|
961 |
|
|
sub GUI_PostEdit($$$) |
962 |
|
|
{ |
963 |
|
|
my ($s, $user, $dbh) = @_; |
964 |
|
|
my $q = $s->{cgi}; |
965 |
|
|
my $action = $q->param('post_action'); |
966 |
|
|
if(not defined $action) { return; } |
967 |
|
|
|
968 |
|
|
if(defined $q->param('button_cancel')) { return; } |
969 |
|
|
|
970 |
|
|
my $table = $q->url_param('table'); |
971 |
|
|
|
972 |
|
|
## delete |
973 |
|
|
if($action eq 'delete') { |
974 |
|
|
if(!DB_DeleteRecord($dbh,$table,$q->param('id'))) { |
975 |
|
|
my %template_args = ( |
976 |
|
|
PAGE => 'db_error', |
977 |
|
|
USER => $user, |
978 |
|
|
TITLE => 'Database Error' |
979 |
|
|
); |
980 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
981 |
|
|
GUI_Header($s, \%template_args); |
982 |
|
|
$template_args{ELEMENT}='db_error'; |
983 |
|
|
$template_args{ERROR}=$g{db_error}; |
984 |
|
|
$template_args{NEXT_URL}=MyURL($q); |
985 |
|
|
print Template(\%template_args); |
986 |
|
|
GUI_Footer(\%template_args); |
987 |
|
|
exit; |
988 |
|
|
} |
989 |
|
|
} |
990 |
|
|
|
991 |
|
|
|
992 |
|
|
## add or edit: |
993 |
|
|
my %record; |
994 |
|
|
if($action eq 'add' || $action eq 'edit'){ |
995 |
|
|
for my $field (@{$g{db_fields_list}{$table}}) { |
996 |
|
|
my $value = GUI_WidgetRead($s, "field_$field", $g{db_fields}{$table}{$field}{widget}); |
997 |
|
|
if(defined $value) { |
998 |
|
|
$record{$field} = $value; |
999 |
|
|
} |
1000 |
|
|
} |
1001 |
|
|
} |
1002 |
|
|
if($action eq 'add') { |
1003 |
|
|
if(!DB_AddRecord($dbh,$table,\%record)) { |
1004 |
|
|
my $data = GUI_Hash2Str(\%record); |
1005 |
|
|
GUI_Edit_Error($s, $user, $g{db_error}, |
1006 |
|
|
$q->param('form_url'), $data, $action); |
1007 |
|
|
} |
1008 |
|
|
} |
1009 |
|
|
elsif($action eq 'edit') { |
1010 |
|
|
$record{id} = $q->param('id'); |
1011 |
|
|
if(!DB_UpdateRecord($dbh,$table,\%record)) { |
1012 |
|
|
my $data = GUI_Hash2Str(\%record); |
1013 |
|
|
GUI_Edit_Error($s, $user, $g{db_error}, |
1014 |
|
|
$q->param('form_url'), $data, $action); |
1015 |
|
|
} |
1016 |
|
|
} |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
sub GUI_Edit($$$) |
1020 |
|
|
{ |
1021 |
|
|
my ($s, $user, $dbh) = @_; |
1022 |
|
|
my $q = $s->{cgi}; |
1023 |
|
|
my $action = $q->url_param('action'); |
1024 |
|
|
my $table = $q->url_param('table'); |
1025 |
|
|
my $id = $q->url_param('id'); |
1026 |
|
|
|
1027 |
|
|
my $reedit = undef; |
1028 |
|
|
if($action eq 'reedit') { |
1029 |
|
|
$reedit = 1; |
1030 |
|
|
$action = $q->url_param('reedit_action'); |
1031 |
|
|
} |
1032 |
|
|
|
1033 |
|
|
if(not exists $g{db_tables}{$table}) { |
1034 |
|
|
die "Error: no such table ($table)"; |
1035 |
|
|
} |
1036 |
|
|
|
1037 |
|
|
my $title = $g{db_tables}{$table}{desc}; |
1038 |
|
|
$title =~ s/s\s*$//; # very rough :-) |
1039 |
|
|
$title =~ s/^. //; |
1040 |
|
|
my %template_args = ( |
1041 |
|
|
USER => $user, |
1042 |
|
|
PAGE => 'edit', |
1043 |
|
|
TABLE => $table, |
1044 |
|
|
TITLE => $action eq 'add' ? "New $title" : "Edit $title", |
1045 |
|
|
ACTION => $action, |
1046 |
|
|
ID => $id, |
1047 |
|
|
REEDIT => $reedit, |
1048 |
|
|
); |
1049 |
|
|
|
1050 |
|
|
my $form_url = MakeURL($s->{url}, { refresh => NextRefresh() }); |
1051 |
|
|
my $next_url; |
1052 |
|
|
my $cancel_url = MakeURL($form_url, { |
1053 |
|
|
action => 'list', |
1054 |
|
|
id => '', |
1055 |
|
|
reedit_action => '', |
1056 |
|
|
reedit_data => '', |
1057 |
|
|
}); |
1058 |
|
|
if($action eq 'add') { |
1059 |
|
|
$next_url = MakeURL($form_url, { |
1060 |
|
|
action => $action, |
1061 |
|
|
reedit_action => '', |
1062 |
|
|
reedit_data => '', |
1063 |
|
|
}); |
1064 |
|
|
} |
1065 |
|
|
else { |
1066 |
|
|
$next_url = $cancel_url; |
1067 |
|
|
} |
1068 |
|
|
|
1069 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
1070 |
|
|
GUI_Header($s, \%template_args); |
1071 |
|
|
|
1072 |
|
|
# FORM |
1073 |
|
|
UniqueFormStart($s, $next_url); |
1074 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"post_action\" VALUE=\"$action\">\n"; |
1075 |
|
|
|
1076 |
|
|
# Initialise values |
1077 |
|
|
my $fields = $g{db_fields}{$table}; |
1078 |
|
|
my @fields_list = @{$g{db_fields_list}{$table}}; |
1079 |
|
|
my %values = (); |
1080 |
|
|
if($reedit) { |
1081 |
|
|
GUI_Str2Hash($q->param('reedit_data'), \%values); |
1082 |
|
|
} |
1083 |
|
|
elsif($action eq 'edit') { |
1084 |
|
|
my %record = (); |
1085 |
|
|
DB_GetRecord($dbh,$table,$id,\%values); |
1086 |
|
|
} |
1087 |
|
|
elsif($action eq 'add') { |
1088 |
|
|
# take filterfirst value if set |
1089 |
|
|
my $ff_field = $g{db_tables}{$table}{meta}{filterfirst}; |
1090 |
|
|
my $ff_value = $q->url_param('filterfirst') || $q->url_param('combo_filterfirst') || ''; |
1091 |
|
|
if(defined $ff_value and defined $ff_field) { |
1092 |
|
|
if(defined $g{db_fields}{$table}{$ff_field}{ref_hid}) { |
1093 |
|
|
# convert ID reference to HID |
1094 |
|
|
$values{$ff_field} = DB_ID2HID($dbh, $g{db_fields}{$table}{$ff_field}{reference}, $ff_value); |
1095 |
|
|
} |
1096 |
|
|
} |
1097 |
|
|
# copy fields from previous add form |
1098 |
|
|
for my $field (@fields_list) { |
1099 |
|
|
if($g{db_fields}{$table}{$field}{copy}) { |
1100 |
|
|
# FIXME: find out how this works with files. |
1101 |
|
|
# I think we don't want to copy a file. |
1102 |
|
|
my $v = GUI_WidgetRead($s, "field_$field", $g{db_fields}{$table}{$field}{widget}); |
1103 |
|
|
$values{$field} = $v if defined $v; |
1104 |
|
|
} |
1105 |
|
|
} |
1106 |
|
|
} |
1107 |
|
|
|
1108 |
|
|
if($action eq 'edit') { |
1109 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n"; |
1110 |
|
|
} |
1111 |
|
|
|
1112 |
|
|
# Fields |
1113 |
|
|
$template_args{ELEMENT} = 'editform_header'; |
1114 |
|
|
print Template(\%template_args); |
1115 |
|
|
|
1116 |
|
|
my $field; |
1117 |
|
|
my $n=0; |
1118 |
|
|
foreach $field (@fields_list) { |
1119 |
|
|
if($field eq "${table}_id") { next; } |
1120 |
|
|
|
1121 |
|
|
my $value = exists $values{$field} ? $values{$field} : ''; |
1122 |
|
|
# get default from DB |
1123 |
|
|
if(not defined $value or $value eq '') { |
1124 |
|
|
$value = DB_GetDefault($dbh,$table,$field); |
1125 |
|
|
} |
1126 |
|
|
|
1127 |
|
|
my $inputelem = GUI_WidgetWrite($s, "field_$field", $fields->{$field}{widget},$value); |
1128 |
|
|
|
1129 |
|
|
$template_args{ELEMENT} = 'editfield'; |
1130 |
|
|
$template_args{FIELD} = $field; |
1131 |
|
|
$template_args{LABEL} = $fields->{$field}{desc}; |
1132 |
|
|
$template_args{INPUT} = $inputelem, |
1133 |
|
|
$template_args{TWOCOL} = $n%2; |
1134 |
|
|
print Template(\%template_args); |
1135 |
|
|
$n++; |
1136 |
|
|
} |
1137 |
|
|
delete $template_args{FIELD}; |
1138 |
|
|
delete $template_args{LABEL}; |
1139 |
|
|
delete $template_args{INPUT}; |
1140 |
|
|
|
1141 |
|
|
# Fields |
1142 |
|
|
$template_args{ELEMENT} = 'editform_footer'; |
1143 |
|
|
print Template(\%template_args); |
1144 |
|
|
|
1145 |
|
|
# Buttons |
1146 |
|
|
$template_args{ELEMENT} = 'buttons'; |
1147 |
|
|
$template_args{CANCEL_URL} = $cancel_url; |
1148 |
|
|
print Template(\%template_args); |
1149 |
|
|
|
1150 |
|
|
UniqueFormEnd($s, $form_url, $next_url); |
1151 |
|
|
GUI_Footer(\%template_args); |
1152 |
|
|
} |
1153 |
|
|
|
1154 |
|
|
sub GUI_Pearl($) |
1155 |
|
|
{ |
1156 |
|
|
my $s = shift; |
1157 |
|
|
my $dbh = $s->{dbh}; |
1158 |
|
|
my $user = $s->{user}; |
1159 |
|
|
my $q = $s->{cgi}; |
1160 |
|
|
my $pearl = $q->url_param('pearl'); |
1161 |
|
|
|
1162 |
|
|
if(not exists $g{pearls}{$pearl}) { |
1163 |
|
|
die "Error: pearl named $pearl is known"; |
1164 |
|
|
} |
1165 |
|
|
my $p = $g{pearls}{$pearl}; |
1166 |
|
|
|
1167 |
|
|
my $title = ($p->info())[0]; |
1168 |
|
|
my %template_args = ( |
1169 |
|
|
USER => $user, |
1170 |
|
|
PAGE => 'edit', |
1171 |
|
|
TABLE => '', |
1172 |
|
|
TITLE => "Configure $title", |
1173 |
|
|
BUTTON_LABEL => 'Run Report', |
1174 |
|
|
); |
1175 |
|
|
|
1176 |
|
|
my $form_url = MakeURL(MyURL($q),{}); |
1177 |
|
|
my $cancel_url = MakeURL($form_url, { |
1178 |
|
|
action => 'entry'}); |
1179 |
|
|
|
1180 |
|
|
my $next_url = $form_url; |
1181 |
|
|
|
1182 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
1183 |
|
|
GUI_Header($s, \%template_args); |
1184 |
|
|
|
1185 |
|
|
# FORM |
1186 |
|
|
FormStart($s, $next_url); |
1187 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"action\" VALUE=\"runpearl\">\n"; |
1188 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"pearl\" VALUE=\"$pearl\">\n"; |
1189 |
|
|
# Fields |
1190 |
|
|
$template_args{ELEMENT} = 'editform_header'; |
1191 |
|
|
print Template(\%template_args); |
1192 |
|
|
|
1193 |
|
|
my $field; |
1194 |
|
|
my $n; |
1195 |
|
|
for (@{$g{pearls}{$pearl}->template()}){ |
1196 |
|
|
my ($field,$label,$widget,$value,$test) = @$_; |
1197 |
|
|
my $inputelem = GUI_WidgetWrite($s,"field_$field",$widget,$value); |
1198 |
|
|
|
1199 |
|
|
$template_args{ELEMENT} = 'editfield'; |
1200 |
|
|
$template_args{FIELD} = $field; |
1201 |
|
|
$template_args{LABEL} = $label; |
1202 |
|
|
$template_args{INPUT} = $inputelem, |
1203 |
|
|
$template_args{TWOCOL} = $n%2; |
1204 |
|
|
print Template(\%template_args); |
1205 |
|
|
$n++; |
1206 |
|
|
} |
1207 |
|
|
delete $template_args{FIELD}; |
1208 |
|
|
delete $template_args{LABEL}; |
1209 |
|
|
delete $template_args{INPUT}; |
1210 |
|
|
|
1211 |
|
|
# Fields |
1212 |
|
|
$template_args{ELEMENT} = 'editform_footer'; |
1213 |
|
|
print Template(\%template_args); |
1214 |
|
|
|
1215 |
|
|
# Buttons |
1216 |
|
|
$template_args{ELEMENT} = 'buttons'; |
1217 |
|
|
$template_args{CANCEL_URL} = $cancel_url; |
1218 |
|
|
print Template(\%template_args); |
1219 |
|
|
|
1220 |
|
|
FormEnd($s); |
1221 |
|
|
GUI_Footer(\%template_args); |
1222 |
|
|
} |
1223 |
|
|
|
1224 |
|
|
sub GUI_MakeCombo($$$$) |
1225 |
|
|
{ |
1226 |
|
|
my ($dbh, $combo_view, $name, $value) = @_; |
1227 |
|
|
|
1228 |
|
|
$value =~ s/^\s+//; |
1229 |
|
|
$value =~ s/\s+$//; |
1230 |
|
|
|
1231 |
|
|
my $str; |
1232 |
|
|
|
1233 |
|
|
my @combo; |
1234 |
|
|
if(not defined DB_GetCombo($dbh,$combo_view,\@combo)) { |
1235 |
|
|
return undef; |
1236 |
|
|
} |
1237 |
|
|
|
1238 |
|
|
$str = "<SELECT SIZE=\"1\" name=\"$name\">\n"; |
1239 |
|
|
# the empty option must not be empty! else the MORE ... disapears off screen |
1240 |
|
|
$str .= "<OPTION VALUE=\"\">Make your Choice ...</OPTION>\n"; |
1241 |
|
|
foreach(@combo) { |
1242 |
|
|
my $id = $_->[0]; |
1243 |
|
|
$id=~s/^\s+//; $id=~s/\s+$//; |
1244 |
|
|
#my $text = "$_->[0] -- $_->[1]"; |
1245 |
|
|
my $text = $_->[1]; |
1246 |
|
|
if($value eq $id) { |
1247 |
|
|
$str .= "<OPTION SELECTED VALUE=\"$id\">$text</OPTION>\n"; |
1248 |
|
|
} |
1249 |
|
|
else { |
1250 |
|
|
$str .= "<OPTION VALUE=\"$id\">$text</OPTION>\n"; |
1251 |
|
|
} |
1252 |
|
|
} |
1253 |
|
|
$str .= "</SELECT>\n"; |
1254 |
|
|
return $str; |
1255 |
|
|
} |
1256 |
|
|
|
1257 |
|
|
sub GUI_MakeISearch($$$$$$) |
1258 |
|
|
{ |
1259 |
|
|
my $ref_target = shift; |
1260 |
|
|
my $input_name = shift; |
1261 |
|
|
my $ticket = shift; |
1262 |
|
|
my $myurl = shift; |
1263 |
|
|
my $value = shift; |
1264 |
|
|
my $hidisearch = shift; |
1265 |
|
|
|
1266 |
|
|
$value =~ s/^\s+//; |
1267 |
|
|
$value =~ s/\s+$//; |
1268 |
|
|
|
1269 |
|
|
|
1270 |
|
|
my $targeturl = MakeURL($myurl,{action=>'dumptable',table=>$ref_target,ticket=>$ticket}); |
1271 |
|
|
|
1272 |
|
|
my $html; |
1273 |
|
|
$html .= "<input type=\"button\" onclick=\""; |
1274 |
|
|
$html .= "document.editform.$input_name.value=document.isearch_$input_name.getID('$value')"; |
1275 |
|
|
$html .= ";\" value=\"I-Search\"> "; |
1276 |
|
|
$html .= "<applet id=\"isearch_$input_name\" name=\"isearch_$input_name\""; |
1277 |
|
|
$html .= ' code="ISearch.class" width="70" height="20" archive="'.$g{conf}{isearch}.'">'."\n"; |
1278 |
|
|
$html .= GUI_AppletParam("url",$targeturl); |
1279 |
|
|
if($hidisearch){ |
1280 |
|
|
$html .= GUI_AppletParam("hid","true"); |
1281 |
|
|
} |
1282 |
|
|
$html .= "</applet>\n"; |
1283 |
|
|
|
1284 |
|
|
return $html |
1285 |
|
|
} |
1286 |
|
|
|
1287 |
|
|
sub GUI_AppletParam($$){ |
1288 |
|
|
my $name=shift; |
1289 |
|
|
my $value=shift; |
1290 |
|
|
return "<param name=\"$name\" value=\"$value\">\n"; |
1291 |
|
|
} |
1292 |
|
|
|
1293 |
|
|
|
1294 |
|
|
|
1295 |
|
|
sub GUI_WidgetWrite($$$$) |
1296 |
|
|
{ |
1297 |
|
|
my ($s, $input_name, $widget, $value) = @_; |
1298 |
|
|
|
1299 |
|
|
my $q = $s->{cgi}; |
1300 |
|
|
my $dbh = $s->{dbh}; |
1301 |
|
|
my $myurl = MyURL($q); |
1302 |
|
|
|
1303 |
|
|
if(not defined $value) { $value = ''; } |
1304 |
|
|
|
1305 |
|
|
my ($w, $warg) = DB_ParseWidget($widget); |
1306 |
|
|
|
1307 |
|
|
my $escval = $value; |
1308 |
|
|
$escval =~ s/\"/"/g; |
1309 |
|
|
|
1310 |
|
|
if($w eq 'readonly') { |
1311 |
|
|
return $value || ' '; |
1312 |
|
|
} |
1313 |
|
|
elsif($w eq 'text') { |
1314 |
|
|
my $size = defined $warg->{size} ? $warg->{size} : '20'; |
1315 |
|
|
return "<INPUT TYPE=\"text\" NAME=\"$input_name\" SIZE=\"$size\" VALUE=\"".$escval."\">"; |
1316 |
|
|
} |
1317 |
|
|
elsif($w eq 'area') { |
1318 |
|
|
my $rows = defined $warg->{rows} ? $warg->{rows} : '4'; |
1319 |
|
|
my $cols = defined $warg->{cols} ? $warg->{cols} : '60'; |
1320 |
|
|
return "<TEXTAREA NAME=\"$input_name\" ROWS=\"$rows\" COLS=\"$cols\" WRAP=\"virtual\">".$value."</TEXTAREA>"; |
1321 |
|
|
} |
1322 |
|
|
elsif($w eq 'varchar') { |
1323 |
|
|
my $size = defined $warg->{size} ? $warg->{size} : '20'; |
1324 |
|
|
my $maxlength = defined $warg->{maxlength} ? $warg->{maxlength} : '100'; |
1325 |
|
|
return "<INPUT TYPE=\"text\" NAME=\"$input_name\" SIZE=\"$size\" MAXLENGTH=\"$maxlength\" VALUE=\"$escval\">"; |
1326 |
|
|
} |
1327 |
|
|
elsif($w eq 'checkbox') { |
1328 |
|
|
return "<INPUT TYPE=\"checkbox\" NAME=\"$input_name\" VALUE=\"1\"".($value ? 'CHECKED' : '').">"; |
1329 |
|
|
} |
1330 |
|
|
elsif($w eq 'hid') { |
1331 |
|
|
return "<INPUT TYPE=\"text\" NAME=\"$input_name\" SIZE=\"10\" VALUE=\"".$escval."\">"; |
1332 |
|
|
} |
1333 |
|
|
elsif($w eq 'isearch' or $w eq 'hidisearch') { |
1334 |
|
|
my $out; |
1335 |
|
|
my $hidisearch; |
1336 |
|
|
$hidisearch = 0; |
1337 |
|
|
if($w eq 'hidisearch') { |
1338 |
|
|
# replace value with HID if 'hidcombo' |
1339 |
|
|
$value = DB_ID2HID($dbh,$warg->{'ref'},$value); |
1340 |
|
|
$hidisearch=1; |
1341 |
|
|
} |
1342 |
|
|
|
1343 |
|
|
my $combo = GUI_MakeISearch($warg->{'ref'}, $input_name, |
1344 |
|
|
$s->{ticket_value}, $myurl, $value, $hidisearch); |
1345 |
|
|
|
1346 |
|
|
$out.="<INPUT TYPE=\"text\" NAME=\"$input_name\" SIZE=10"; |
1347 |
|
|
$out .= " VALUE=\"$value\""; |
1348 |
|
|
$out .= ">\n$combo"; |
1349 |
|
|
return $out; |
1350 |
|
|
} |
1351 |
|
|
elsif($w eq 'idcombo' or $w eq 'hidcombo') { |
1352 |
|
|
my $out; |
1353 |
|
|
my $combo; |
1354 |
|
|
|
1355 |
|
|
if($g{conf}{gedafe_compat} eq '1.0') { |
1356 |
|
|
$value = DB_ID2HID($dbh,$warg->{'ref'},$value) if $w eq 'hidcombo'; |
1357 |
|
|
$combo = GUI_MakeCombo($dbh, $warg->{'combo'}, "${input_name}_combo", $value); |
1358 |
|
|
} |
1359 |
|
|
else { |
1360 |
|
|
$combo = GUI_MakeCombo($dbh, $warg->{'combo'}, "${input_name}_combo", $value); |
1361 |
|
|
$value = DB_ID2HID($dbh,$warg->{'ref'},$value) if $w eq 'hidcombo'; |
1362 |
|
|
} |
1363 |
|
|
$out .= "<INPUT TYPE=\"text\" NAME=\"$input_name\" SIZE=10"; |
1364 |
|
|
if($combo !~ /SELECTED/ and defined $value) { |
1365 |
|
|
$out .= " VALUE=\"$value\""; |
1366 |
|
|
} |
1367 |
|
|
$out .= ">\n$combo"; |
1368 |
|
|
return $out; |
1369 |
|
|
} |
1370 |
|
|
elsif($w eq 'combo') { |
1371 |
|
|
return GUI_MakeCombo($dbh, $warg->{'combo'}, "${input_name}_combo", $value); |
1372 |
|
|
} |
1373 |
|
|
elsif($w eq 'file'){ |
1374 |
|
|
my $filename = $value ne '' ? $value : "(none)"; |
1375 |
|
|
my $out = "Current file: <b>$filename</b>"; |
1376 |
|
|
if($value ne ''){ |
1377 |
|
|
$out .= "<br>Delete file?: <INPUT TYPE=\"checkbox\" NAME=\"file_delete_$input_name\">"; |
1378 |
|
|
} |
1379 |
|
|
$out .= "<br>Enter filename to update.<br><INPUT TYPE=\"file\" NAME=\"$input_name\">"; |
1380 |
|
|
return $out; |
1381 |
|
|
} |
1382 |
|
|
elsif($w eq 'date') { |
1383 |
|
|
return GUI_WidgetWrite_Date($input_name, $warg, $value); |
1384 |
|
|
} |
1385 |
|
|
|
1386 |
|
|
return "Unknown widget: $w"; |
1387 |
|
|
} |
1388 |
|
|
|
1389 |
|
|
sub GUI_WidgetWrite_Date($$$) |
1390 |
|
|
{ |
1391 |
|
|
my ($input_name, $warg, $value) = @_; |
1392 |
|
|
my ($value_y, $value_m, $value_d) = (0, 0, 0); |
1393 |
|
|
my $escval = $value; $escval =~ s/\"/"/g; |
1394 |
|
|
|
1395 |
|
|
my @months; |
1396 |
|
|
if($warg->{short}) { |
1397 |
|
|
@months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", |
1398 |
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); |
1399 |
|
|
} |
1400 |
|
|
else { |
1401 |
|
|
@months = ("January", "February", "March", "April", |
1402 |
|
|
"May", "June", "July", "August", "September", |
1403 |
|
|
"October", "November", "December"); |
1404 |
|
|
} |
1405 |
|
|
|
1406 |
|
|
my $yearselect = "<option>(year)</option>\n"; |
1407 |
|
|
my $dayselect = "<option>(day)</option>\n"; |
1408 |
|
|
my $monthselect = "<option>(month)</option>\n"; |
1409 |
|
|
|
1410 |
|
|
if($value =~ /(\d+)-(\d+)-(\d+)/) { |
1411 |
|
|
($value_y, $value_m, $value_d) = ($1, $2, $3); |
1412 |
|
|
} |
1413 |
|
|
|
1414 |
|
|
for my $y (($warg->{from})..($warg->{to})) { |
1415 |
|
|
if ($y == $value_y) { |
1416 |
|
|
$yearselect .= "<option selected>$y</option>\n"; |
1417 |
|
|
} |
1418 |
|
|
else { |
1419 |
|
|
$yearselect .= "<option>$y</option>\n"; |
1420 |
|
|
} |
1421 |
|
|
} |
1422 |
|
|
for my $m (0..11) { |
1423 |
|
|
if ($m+1 == $value_m) { |
1424 |
|
|
$monthselect .= "<option selected>$months[$m]</option>\n"; |
1425 |
|
|
} |
1426 |
|
|
else { |
1427 |
|
|
$monthselect .= "<option>$months[$m]</option>\n"; |
1428 |
|
|
} |
1429 |
|
|
} |
1430 |
|
|
for my $d (1..31) { |
1431 |
|
|
if ($d == $value_d) { |
1432 |
|
|
$dayselect .= "<option selected>$d</option>\n"; |
1433 |
|
|
} |
1434 |
|
|
else { |
1435 |
|
|
$dayselect .= "<option>$d</option>\n"; |
1436 |
|
|
} |
1437 |
|
|
} |
1438 |
|
|
|
1439 |
|
|
my $yearinput = $input_name.'_1'; |
1440 |
|
|
my $monthinput = $input_name.'_2'; |
1441 |
|
|
my $dayinput = $input_name.'_3'; |
1442 |
|
|
my $functionname = $input_name.'_validate'; |
1443 |
|
|
my $out =<<end; |
1444 |
|
|
<SCRIPT LANGUAGE="JavaScript"> |
1445 |
|
|
<!-- |
1446 |
|
|
function $functionname(){ |
1447 |
|
|
var leap = 0; |
1448 |
|
|
|
1449 |
|
|
//get variables from form |
1450 |
|
|
var year = document.editform.$yearinput.selectedIndex; |
1451 |
|
|
var month = document.editform.$monthinput.selectedIndex; |
1452 |
|
|
var day = document.editform.$dayinput.selectedIndex; |
1453 |
|
|
|
1454 |
|
|
// if year month or date are on the (first) empty field |
1455 |
|
|
// then the date is invalid. Clear the field to reflect that. |
1456 |
|
|
if(year == 0 || month == 0 || day == 0){ |
1457 |
|
|
document.editform.$input_name.value = ""; |
1458 |
|
|
return; |
1459 |
|
|
} |
1460 |
|
|
|
1461 |
|
|
year = $warg->{from} + year - 1; |
1462 |
|
|
|
1463 |
|
|
// is this a leap year? |
1464 |
|
|
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))){ |
1465 |
|
|
leap = 1; |
1466 |
|
|
} |
1467 |
|
|
|
1468 |
|
|
|
1469 |
|
|
//update form to reflect corretions on date |
1470 |
|
|
if ((month == 2) && (leap == 1) && (day > 29)){ |
1471 |
|
|
document.editform.$dayinput.selectedIndex = 29; |
1472 |
|
|
day = 29; |
1473 |
|
|
} |
1474 |
|
|
|
1475 |
|
|
if ((month == 2) && (leap != 1) && (day > 28)){ |
1476 |
|
|
document.editform.$dayinput.selectedIndex = 28; |
1477 |
|
|
day = 28; |
1478 |
|
|
} |
1479 |
|
|
|
1480 |
|
|
if ((day > 30) && ((month == 4) || (month == 6) || (month == 9) || (month == 11))){ |
1481 |
|
|
document.editform.$dayinput.selectedIndex = 30; |
1482 |
|
|
day = 30; |
1483 |
|
|
} |
1484 |
|
|
|
1485 |
|
|
|
1486 |
|
|
var date = year + "-" + month + "-" + day; |
1487 |
|
|
|
1488 |
|
|
|
1489 |
|
|
document.editform.$input_name.value = date; |
1490 |
|
|
} |
1491 |
|
|
// --> |
1492 |
|
|
</script> |
1493 |
|
|
|
1494 |
|
|
<select NAME="$yearinput" onChange="$functionname()"> |
1495 |
|
|
$yearselect</select> |
1496 |
|
|
|
1497 |
|
|
<select NAME="$monthinput" onChange="$functionname()"> |
1498 |
|
|
$monthselect</select> |
1499 |
|
|
|
1500 |
|
|
<select NAME="$dayinput" onChange="$functionname()"> |
1501 |
|
|
$dayselect</select> |
1502 |
|
|
|
1503 |
|
|
<input TYPE="hidden" NAME="$input_name" VALUE="$escval"> |
1504 |
|
|
end |
1505 |
|
|
return $out; |
1506 |
|
|
} |
1507 |
|
|
|
1508 |
|
|
sub GUI_Delete($$$) |
1509 |
|
|
{ |
1510 |
|
|
my ($s, $user, $dbh) = @_; |
1511 |
|
|
my $q = $s->{cgi}; |
1512 |
|
|
my $table = $q->url_param('table'); |
1513 |
|
|
my $id = $q->url_param('id'); |
1514 |
|
|
my $next_url = MakeURL($s->{url}, { action=>'list', id=>'' }); |
1515 |
|
|
|
1516 |
|
|
my %template_args = ( |
1517 |
|
|
PAGE => 'delete', |
1518 |
|
|
USER => $user, |
1519 |
|
|
TITLE => "Delete Record", |
1520 |
|
|
TABLE => $table, |
1521 |
|
|
ID => $id, |
1522 |
|
|
NEXT_URL => $next_url, |
1523 |
|
|
); |
1524 |
|
|
|
1525 |
|
|
GUI_InitTemplateArgs($s, \%template_args); |
1526 |
|
|
GUI_Header($s, \%template_args); |
1527 |
|
|
UniqueFormStart($s, $next_url); |
1528 |
|
|
|
1529 |
|
|
$template_args{ELEMENT}='delete'; |
1530 |
|
|
print Template(\%template_args); |
1531 |
|
|
|
1532 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"post_action\" VALUE=\"delete\">\n"; |
1533 |
|
|
print "<INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n"; |
1534 |
|
|
UniqueFormEnd($s, $next_url, $next_url); |
1535 |
|
|
GUI_Footer(\%template_args); |
1536 |
|
|
} |
1537 |
|
|
|
1538 |
|
|
sub GUI_DumpTable($$$){ |
1539 |
|
|
my $s = shift; |
1540 |
|
|
my $q = $s->{cgi}; |
1541 |
|
|
my $user = shift; |
1542 |
|
|
my $dbh = shift; |
1543 |
|
|
my $myurl = MyURL($q); |
1544 |
|
|
my $table = $q->url_param('table'); |
1545 |
|
|
|
1546 |
|
|
my %atribs; |
1547 |
|
|
foreach($q->param) { |
1548 |
|
|
if(/^field_(.*)/) { |
1549 |
|
|
$atribs{$1} = $q->param($_); |
1550 |
|
|
} |
1551 |
|
|
} |
1552 |
|
|
my $data; |
1553 |
|
|
my $first = 1; |
1554 |
|
|
|
1555 |
|
|
my $view = defined $g{db_tables}{"${table}_list"} ? |
1556 |
|
|
"${table}_list" : $table; |
1557 |
|
|
|
1558 |
|
|
my @fields_list = @{$g{db_fields_list}{$view}}; |
1559 |
|
|
for (@fields_list){ |
1560 |
|
|
if(not $first){ |
1561 |
|
|
$data.="\t"; |
1562 |
|
|
} |
1563 |
|
|
$first = 0; |
1564 |
|
|
$data.=$_; |
1565 |
|
|
} |
1566 |
|
|
$data.="\n"; |
1567 |
|
|
|
1568 |
|
|
$data .= DB_DumpTable($dbh,$table,\%atribs); |
1569 |
|
|
print $data; |
1570 |
|
|
} |
1571 |
|
|
|
1572 |
|
|
1; |
1573 |
|
|
# Emacs Configuration |
1574 |
|
|
# |
1575 |
|
|
# Local Variables: |
1576 |
|
|
# mode: cperl |
1577 |
|
|
# eval: (cperl-set-style "BSD") |
1578 |
|
|
# cperl-indent-level: 8 |
1579 |
|
|
# mode: flyspell |
1580 |
|
|
# mode: flyspell-prog |
1581 |
|
|
# End: |
1582 |
|
|
# |
1583 |
|
|
|
1584 |
|
|
# vi: tw=0 sw=8 |