$xml
? ["\n\n"
,"\n", '', '', ' ', ' ', '', " \n", " \n", "
\n"]
: !$b
? ["\n$tcf0\n"
, "\n"
, ""
, "'
, ' ', '', " \n", " \n", "
\n"]
: $b =~/\n"
? [$b, '', '', '', ' - ', '', " \n", " "]
: ["", ' ', ' ', " ', ' ', '', ' ', "$b\n", " \n"]
if !ref($b);
if (ref($href) eq 'HASH') {
if (!$href->{-key}) { # Hyperlink key
$href->{-key} =[];
my $j =0;
my $k =(ref($m->{-key}) eq 'ARRAY') && $m->{-key};
foreach my $f (@$mf) {
next if ref($f) ne 'HASH' ||!$f->{-fld};
push @{$href->{-key}}, [$f->{-fld} =>&$coln($f,$j)]
if ($f->{-flg}||'') =~/[k]/ # 'k'ey
|| ($k
&& grep {$f->{-fld} eq $_} @$k);
$j++
}
}
elsif((ref($href->{-key}) eq 'ARRAY') || !ref($href->{-key})) {
foreach my $k (ref($href->{-key}) ? @{$href->{-key}} : ($href->{-key})) {
next if ref($k);
if ($i->{NAME}) {
$k =ref($href->{-key}) ? [$k, &$coln($k)] : &$coln($k);
next
}
my $j =0;
foreach my $f (@$mf) {
next if ref($f) ne 'HASH' ||!$f->{-fld};
if ($k eq $f->{-fld}) {
$k =ref($href->{-key}) ? [$k, $j] : $j;
last
}
$j++
}
}
}
if (!$href->{-urm}) { # Hyperlink unread mark
$href->{-urm} =[];
my $j =0;
my $k =((ref($m->{-urm}) eq 'ARRAY') && $m->{-urm})
|| ((ref($mt->{-urm}) eq 'ARRAY') && $mt->{-urm})
|| ((ref($m->{-wkey}) eq 'ARRAY') && $m->{-wkey});
foreach my $f (@$mf) {
next if ref($f) ne 'HASH' ||!$f->{-fld};
push @{$href->{-urm}}, [$f->{-fld} =>&$coln($f,$j)]
if $k
? (grep {$f->{-fld} eq $_} @$k)
: ( ($f->{-flg}||'') =~/[w]/ # 'w'here key
&& ($f->{-flg}||'') !~/[k]/ # 'k'ey
);
$j++
}
}
elsif ((ref($href->{-urm}) eq 'ARRAY') || !ref($href->{-urm})) {
foreach my $k (ref($href->{-urm}) ? @{$href->{-urm}} : $href->{-urm}) {
next if ref($k);
if ($i->{NAME}) {
$k =ref($href->{-urm}) ? [$k, &$coln($k)] : &$coln($k);
next
}
my $j =0;
foreach my $f (@$mf) {
next if ref($f) ne 'HASH' ||!$f->{-fld};
if ($k eq $f->{-fld}) {
$k =ref($href->{-urm}) ? [$k, $j] : $j;
last
}
$j++
}
}
}
if ($href->{-formfld}) { # Hyperlink form
my $j =0;
if ($i->{NAME}) {
$j =&$coln($href->{-formfld});
$href->{-form} =sub{$_[1]->[$j]}
}
else { foreach my $f (@$mf) {
next if ref($f) ne 'HASH' ||!$f->{-fld};
if (($f->{-fld}||'') eq $href->{-formfld}) {
$href->{-form} =sub{$_[1]->[$j]};
last
}
$j++
}
}
}
elsif (defined($href->{-formfld})) {
$href->{-form} =''
}
if (1) { # Hyperlink sub{}
my $hr =$href;
$href =sub{
'?' .'_cmd=' .urlEscape($s
, ref($hr->{-cmd}) ne 'CODE'
? $hr->{-cmd} : (&{$hr->{-cmd}}(@_)))
.$HS .'_form=' .urlEscape($s
, ref($hr->{-form}) ne 'CODE'
? $hr->{-form} : (&{$hr->{-form}}(@_)))
.$HS .'_key=' .urlEscape($s
, !ref($hr->{-key})
? $_[1]->[$hr->{-key}]
: ref($hr->{-key}) ne 'CODE'
? strdatah($s, map {($_->[0] => $_[1]->[$_->[1]])} @{$hr->{-key}})
: &{$hr->{-key}}(@_))
.$HS .'_urm=' .urlEscape($s
, !ref($hr->{-urm})
? $_[1]->[$hr->{-urm}]
: ref($hr->{-urm}) ne 'CODE'
? join(',',map {$_[1]->[$_->[1]] ? ($_[1]->[$_->[1]]) : ()} @{$hr->{-urm}})
: &{$hr->{-urm}}(@_))
};
}
}
$href =sub{''} if !$href;
if (!@colf) { # Display column numbers
my $j =0;
foreach my $e ($disp ? @$disp : $i->{NAME} ? @{$i->{NAME}} : @$mf) {
my $f =undef;
if ($disp || $i->{NAME}) {
foreach my $v (@$mf) {
next if ref($v) ne 'HASH'
||!$v->{-fld}
||lc($v->{-fld}) ne $e;
$f =$v; last
}
$f ={-fld=>$e} if !$f
}
else {
next if ref($e) ne 'HASH' ||!$e->{-fld};
$f =$e
}
$j =&$coln($f, $j);
push @colf # name, number/-lsthtml, heading/-ldclass, td, struct
, [$f->{-fld} || ''
, ref($f->{-lsthtml}) eq 'CODE'
? do{ my($i, $c) =($j, $f->{-lsthtml});
sub{local $_=ref($_[4]) ? $_[4]->[$i] : $_[4]; &$c}
}
: $f->{-inp} && !$xml && (ref($s->lngslot($f->{-inp}, '-labels')) eq 'HASH')
? do{ my($i, $c) =($j, $s->lngslot($f->{-inp}, '-labels'));
$c = {map {$c->{$_} && ($c->{$_} =~/^[_\s]+/)
? ($_ => $')
: ($_ => $c->{$_})
} keys %$c} if $c;
sub{ local $_=ref($_[4]) ? $_[4]->[$i] : $_[4];
htmlEscape(undef, defined($c->{$_}) && defined($c->{$_}) ? $c->{$_} : $_)}
}
: $j
, $s->lnglbl($f, '-fld')||'' # heading
, !$b->[2] || $xml #
|| (!$f->{-ldclass} && !$f->{-ldstyle} && !$f->{-ldprop})
|| ($b->[2] !~/^<.*>$/)
? $b->[2]
: do { my $v =$b->[2]; #
if (ref($f->{-ldclass})) {
my($i,$cs,$w) =($j, $f->{-ldclass}, $v);
$v =sub {my $v =ref($w) ? &$w : $w;
local $_=ref($_[4]) ? $_[4]->[$i] : $_[4];
$v =~/\sclass\s*=\s*"/
? $v =~s/\sclass\s*=\s*"([^"]*)"/' class="' .$1 .'; ' .&$cs .'"'/ie
: $v =~s/^(.+)(>)$/$1 .' class="' .&$cs .'"' .$2/ie;
$v}
}
elsif ($f->{-ldclass}) {
$v =~/\sclass\s*=\s*"/
? $v =~s/\sclass\s*=\s*"([^"]*)"/' class="' .$1 .' ' .$f->{-ldclass} .'"'/ie
: $v =~s/^(.+)(>)$/$1 .' class="' .$f->{-ldclass} .'"' .$2/ie
}
if (ref($f->{-ldstyle})) {
my($i,$cs,$cp,$w) =($j, $f->{-ldstyle}, $f->{-ldprop}, $v);
$v =sub {my $v =ref($w) ? &$w : $w;
local $_=ref($_[4]) ? $_[4]->[$i] :$_[4];
$v =~/\sstyle\s*=\s*"/
? $v =~s/\sstyle\s*=\s*"([^"]*)"/' style="' .$1 .'; ' .&$cs .'"'/ie
: $v =~s/^(.+)(>)$/$1 .' style="' .&$cs .'"' .$2/ie;
$v =~s/^(.+)(>)$/$1 .' ' .(ref($cp) ? &$cp : $cp) .'>'/ie
if $cp;
$v}
}
elsif ($f->{-ldstyle}) {
$v =~/\sstyle\s*=\s*"/
? $v =~s/\sstyle\s*=\s*"([^"]*)"/' style="' .$1 .'; ' .$f->{-ldstyle} .'"'/ie
: $v =~s/^(.+)(>)$/$1 .' style="' .$f->{-ldstyle} .'"' .$2/ie;
$v =~s/^(.+)(>)$/$1 .' ' .$f->{-ldprop} .'>'/ie
if $f->{-ldprop};
}
elsif ($f->{-ldprop}) {
$v =~s/^(.+)(>)$/$1 .' ' .$f->{-ldprop} .'>'/ie
}
else {
}
$v }
, $f]
if $disp || $f->{-lsthtml} || (($f->{-flg}||'') =~/[l]/);
$j++
}
if (!@colf && isa($i, 'HASH')) {
@colf =map {[$i->{NAME}->[$_], $_, $i->{NAME}->[$_]
, $b->[2] #
, {}]} (0..$#{$i->{NAME}});
foreach my $h (@colf) {
foreach my $f (@$mf) {
next if (ref($f) ne 'HASH')
|| !$f->{-fld}
|| ($f->{-fld} ne $h->[2]);
$h->[2] =$s->lnglbl($f,'-fld')||''
}
}
}
}
$tstrt =sub{ # Table start sub{}
$s->output($b->[0]); #
if ($xml || !@colf || $b->[0] !~/{-frmLsc}
|| ($mt->{-frmLsc} && !exists($m->{-frmLsc}))) {
my $lsc =$m->{-frmLsc} ||$mt->{-frmLsc};
my $lsf =$mt->{-mdefld} ||{};
my $hstl1 =$hstl =~/(class=")/ ? $` .$1 .'Input ' .$' : $hstl;
$tho =[@{$colf[0]}];
$tho->[2] = sub{
use locale;
my $lsq =$_[0]->{-pcmd}->{-frmLsc}
||(ref($lsc->[0]) eq 'HASH'
? $lsc->[0]->{-val}
: $lsc->[0]->[0]);
'\n"
.join('', map {
my ($v,$l) =ref($_) eq 'HASH'
? ($_->{-val}, $_[0]->lnglbl($_))
: ($_->[0], $_->[1]);
$l =ucfirst($lsf->{$v}
&& $_[0]->lnglbl($lsf->{$v})
|| $_[0]->lng(0,$v))
if !$l;
''
.$_[0]->htmlEscape($l)
." \n"} @$lsc)
." \n"
}
}
elsif ($m->{-frmLso2C}
|| ($mt->{-frmLso2C} && !exists($m->{-frmLso2C}))) {
$tho =[@{$colf[0]}];
$tho->[2] =$m->{-frmLso2C} ||$mt->{-frmLso2C};
}
$s->output("\n"
, (map {('[4]->{-lhclass} ? ' ' .$_->[4]->{-lhclass} .'"': '"')
.($_->[4]->{-lhstyle} ? ' style="' .$_->[4]->{-lhstyle} .'"' : '')
.' title="' .htmlEscape($s, lngcmt($s, $_->[4]) ||$s->lng(1, $_->[0]) ||$_->[2]) .'"'
.($_->[4]->{-lhprop} ? ' ' .$_->[4]->{-lhprop} : '')
.'>'
,ref($_->[2])
? &{$_->[2]}($s, $n, $m, $c)
: htmlEscape($s, $_->[2])
," \n")} $tho ? ($tho, @colf[1..$#colf]) : @colf)
, " \n")
}
elsif (0 && $b->[0] =~/output("\n"
, (map {('[4]->{-lhclass} ? ' ' .$_->[4]->{-lhclass} .'"': '"')
.($_->[4]->{-lhstyle} ? ' style="' .$_->[4]->{-lhstyle} .'"' : '')
.($_->[4]->{-lhprop} ? ' ' .$_->[4]->{-lhprop} : '')
,"> \n")} @colf)
, " \n")
}
};
if (ref($fetch) ne 'CODE') { # Fetch sub{}
my $ft =$fetch;
my $hrc1=$hrcol+1; # $b->[4] || $#colf ? $hrcol+1 : $hrcol;
my $cargo;
$fetch =sub {
my $r;
while($r =$i->fetch()) {
last if !$m->{-qfilter}
|| &{$m->{-qfilter}}($s, $n, $m, $c, $i->{-rec})
}
return(undef) if !$r;
if ($qflgh) {
$s->output((ref($qflgh) eq 'CODE' ? &$qflgh($s) : $qflgh));
&$tstrt();
$qflgh =undef
}
my $h =&$href($s, $r);
$xml
? $s->output(''
, xmlsTag($s, 'tr', 'href'=>$s->url .'/' .$h, '0')
, "\n"
, (map { ref($_->[1])
? ('<', $_->[0], '>'
, &{$_->[1]}($s, $cargo, undef, $i, $r)
, '', $_->[0], ">\n")
: xmlsTag($s, $_->[0]
, ''=> ref($_->[1])
? &{$_->[1]}($s, $cargo, undef, $i, $r)
: ref($r)
? $r->[$_->[1]]
: $r
, "\n")
} @colf)
,$b->[8]) #
: $s->output($b->[1] # ||[3]) ? &{$_->[3]}($s, $cargo, $h, $i, $r) : $_->[3])
||htmlEscBlnk($s, ref($r) ? $r->[$_->[1]] : $r)
, $b->[3] #
, $b->[4] && $h, $b->[4] # "> || ''
, ref($_->[1])
? &{$_->[1]}($s, $cargo, $h, $i, $r)
: htmlEscBlnk($s, ref($r) ? $r->[$_->[1]] : $r)
, $b->[5], $b->[7] # ||'_
)} @colf[0..$hrcol])
, (map {($b->[6] # '' || ' - '
, ref($_->[3])
? &{$_->[3]}($s, $cargo, undef, $i, $r)
: $_->[3] # $b->[2]
, ref($_->[1])
? &{$_->[1]}($s, $cargo, undef, $i, $r)
: htmlEscBlnk($s, ref($r) ? $r->[$_->[1]] : $r)
, $b->[7] #
)} @colf[$hrc1..$#colf])
,$b->[8]) #
}
}
&$tstrt() if !$qflgh; # Table start
my $j =0;
while (&$fetch($s, $i, $b)) { # Fetch data
$j++;
last if $j >$limit;
}
$s->{-fetched} =$j;
$s->{-limited} =$limit;
eval {$i->finish};
$s->output($b->[9]) if !$qflgh; # Table end
}
sub cgiLst { # Simplified 'cgiList' to embed into 'cgiForm'
my $s =shift; # (?options, view, ? query)
my $o =$_[0] =~/^-/ ? shift : '-!h';
my ($f, $q) =@_;
return($s->cgiList($o, $f, undef, {}
,$s->cgiQuery($f, undef, {}))
) if !$q;
$q ={%$q};
foreach my $k (qw(urole uname)) {
$q->{"-q$k"} =$q->{"-$k"} if exists($q->{"-$k"}) && !exists($q->{"-q$k"})
}
foreach my $k (qw(key where ftext version order keyord limit display datainc)) {
$q->{"-q$k"} =$q->{"-$k"} if $q->{"-$k"} && !$q->{"-q$k"}
}
$s->cgiList($o, $f, undef, $q ||{}
,$s->cgiQuery($f, undef, $q))
}
sub cgiHelp { # Print CGI Help screen form
# self, form name, form meta, command, data
my ($s, $n, $m, $c, $d) =@_;
$m =$s->{-form}->{$n}||eval{$s->mdeTable($n)} if !$m;
$c =$s->{-pcmd} if !$c;
$d =$s->{-pout} if !$d;
my $mt=ref($m) && $m->{-table} ? eval{$s->mdeTable($m->{-table})} : $m;
my $cs =join(' '
,$s->{-c}->{-htmlclass} ? $s->htmlEscape($s->{-c}->{-htmlclass}) : ()
,$s->{-uiclass} ? $s->{-uiclass} : ());
my $cs1 =$cs ? 'class="' .$cs .'"' : '';
my $cs2 =$cs ? 'class="' .$cs .'"' : '';
my $th1 ="";
my $td1 =" ";
my $th2 =" ";
my $td2 =" ";
my $th3 =$th2;
my $td3 =$td2;
my $cfs ='';
my $cfe ='
';
my ($th, @td);
my $hl =$LNG->{$s->{-lng}} || $LNG->{''};
my $cl =sub{ my $t =$_[0];
my ($c, $v);
$c =$t;
$v =$c && $hl->{$c} && $hl->{$c}->[0];
return($v) if $v;
$c =substr($t,0,1) eq '-' ? substr($t,1) : $t;
$v =$c && $hl->{$c} && $hl->{$c}->[0];
return($v) if $v;
$t #ucfirst($c)
};
my $cv =sub{ my $v =$_[0];
!defined($v)
? 'undef'
: $v eq ''
? $s->dsdQuot($v)
: ref($v) eq 'CODE'
? 'CODE()'
: ref($v)
? $s->dsdQuot($v)
: $v};
my $cf;
$cf =sub { # (meta, name)
return(join(', ', map {&$cf($_[0],$_,$#_ >1 ? @_[2..$#_] : ())
} @{$_[1]})
) if ref($_[1]) eq 'ARRAY';
my $f =!$_[1]
? undef
: (($_[0]->{-mdefld} && $_[0]->{-mdefld}->{$_[1]})
|| ($mt && $mt->{-mdefld} && $mt->{-mdefld}->{$_[1]}));
$_[2] && $f
? $s->htmlEscape($s->lngcmt($f) ||$s->lng(1,$_[1]))
: $_[2]
? ''
: $f
? ''
.$s->htmlEscape($s->strquot($s->lnglbl($f) ||$s->lng(0,$_[1])))
.' '
: (wantarray() ? () : $s->htmlEscape($s->strquot($_[1])))
};
my $hff={ 'a' =>"all"
,'k' =>"key"
,'w' =>"wkey"
,'e' =>"edit"
,'u' =>"update"
,'m' =>"mandatory"
,'h' =>"hyperlik"
,'q' =>"query"
,'l' =>"list"
,'f' =>"fetch"
,'n' =>"numeric"
,'9' =>"numeric"
,'"' =>"string"
};
my $cff=sub { return('') if !$_[0];
join(', '
, map { $hff->{$_} ? $hff->{$_} : $_
} split / */, $_[0])
};
my $ce =sub { my $v =$s->htmlEscape(@_);
$v =~s/[\r\n]+/ /g;
$v
};
my $ch =sub { my $v =ref($_[0]) ? &{$_[0]}($s) : $_[0];
return $v if ($s->ishtml($v));
&$ce($v)
};
$s->output("\n\n");
if ($s->lngslot($s,'-help')) {
$s->output(""
,$th1
,''
,'', $td1
,&$ch($s->lngslot($s,'-help'))
," \n"
);
}
if (1) {
$s->htmlMChs() if !$s->{-menuchs};
if ($s->{-menuchs}) {
$s->output(
"", $th1, '',''
, $td1
, join(', '
, map {
my ($on, $ol, $ot) =ref($_) eq 'ARRAY' ? (@$_) : ($_);
$on =$' if $on =~/[.^&+]+$/;
my $o =$s->{-form}->{$on} ||$s->{-table}->{$on};
if ($o && !$ol) {
$ol=$_[0]->lngslot($o,'-lbl') if $o;
$ol=&$ol($_[0]) if ref($ol);
$ol =$ol ||$on;
}
if ($o) {
$ot=$_[0]->lngslot($o,'-cmt');
$ot=&$ot($_[0]) if ref($ot);
$ot =$ot ||$on;
}
$ol
? ''
.$s->htmlEscape($ol)
.' '
: ()
} @{$s->{-menuchs}})
, " \n"
);
}
}
foreach my $oc ('f','t') {
my $om;
my $on;
if ($oc eq 'f') {
$on =$n;
$om =$s->{-form}->{$n};
}
elsif ($oc eq 't') {
$om =$s->{-form}->{$n};
$om =!$om ? eval{$s->mdeTable($on =$n)} : $om->{-table} ? eval{$s->mdeTable($on =$om->{-table})} : eval{$s->mdeTable($on =$n)};
}
next if !$om;
$s->output(""
,$th1, " "
,$s->htmlEscape($s->lnglbl($om)||'')
,''
,$td1, " "
,&$ce($s->lngcmt($om)||'')
," \n"
);
$s->output(""
,$th2
,''
,$td2
,&$ch($s->lngslot($om,'-help')||'')
," \n"
) if $s->lngslot($om,'-help');
$th =join(' ', $on ? $on : ());
$th =join('; '
, $th ? $th : ()
, map { !exists($om->{$_}) && !exists($s->{$_})
? ()
: $s->htmlEscape($_
.'=> '
.&$cv(exists($om->{$_})
? $om->{$_}
: $s->{$_}))
} ($om->{-table} && !ref($om->{-table}) ? qw(-table) : ())
, qw(-expr -null)
, (grep {/^-(?:cgc|cgv|subst|redirect)/
} sort keys %$om));
$s->output("",$th2,'',$td2,$cfs,$th,"$cfe \n")
if $th;
($th, @td) =($s->htmlEscape(&$cl('-key')));
foreach my $k ( qw(-key)
, $oc eq 't' ? qw(-wikn) : ()
, qw(-wkey)
, $oc eq 't' ? qw(-ridRef) : ()) {
next if !exists($om->{$k}) && !exists($s->{$k});
my $td =&$cf($om, $om->{$k} ||$s->{$k});
$td .=($hl->{$k} && $hl->{$k}->[1]
? ' - ' .$s->htmlEscape($hl->{$k}->[1])
: '') if $td;
push @td, $td if $td;
}
$s->output("",$td1,$th,'',$td2,join(" \n$td1$td2", @td)," \n")
if @td;
($th, @td) =($s->htmlEscape(&$cl('-rvcActPtr')));
foreach my $k ( $oc eq 't' && ($om->{-rvcActPtr} ||$s->{-rvcActPtr})
? qw(-rvcChgState -rvcCkoState -rvcDelState)
: ()) {
next if !exists($om->{$k}) && !exists($s->{$k});
my $td =$om->{$k}->[0] && &$cf($om,$om->{$k}->[0]);
next if !$td;
my $f =($om->{-mdefld} && $om->{-mdefld}->{$om->{$k}->[0]})
|| ($mt->{-mdefld} && $mt->{-mdefld}->{$om->{$k}->[0]});
my $l =$s->lngslot($f->{-inp},'-labels') ||$f->{-inp}->{-labels}
if $f && $f->{-inp};
$l =undef
if ref($l) ne 'HASH';
$f = ref($f->{-inp}->{-values}) eq 'ARRAY'
? {map {($_=>$l && $l->{$_} ||$s->lng(0,$_) ||$_)
} @{$f->{-inp}->{-values}}}
: $l
if $f && $f->{-inp};
my $v =join(', '
, map{ !$f
? $s->strquot($s->lng(0,$_)||$_)
: $f->{$_}
? $s->strquot($f->{$_})
: ()
} @{$om->{$k}}[1..$#{$om->{$k}}]);
$td =$v ? $td .' = ' .$v : '';
next if !$td;
$td .=($hl->{$k} && $hl->{$k}->[1]
? ' - ' .$s->htmlEscape($hl->{$k}->[1])
: '');
push @td, $td if $td;
}
{ my $k ='-rvcActPtr';
my $v =&$cf($om, $om->{$k} ||$s->{$k});
$v .=$hl->{$k} && $hl->{$k}->[1]
? ' - ' .$s->htmlEscape($hl->{$k}->[1])
: '' if $v;
unshift @td, $v if $v && @td;
}
$s->output("",$td1,$th,'',$td2,join(" \n$td1$td2", @td)," \n")
if @td;
($th, @td) =($s->htmlEscape(&$cl('-racUser')));
foreach my $k ( $oc eq 't'
?($s->{-rac} ? qw(-racWriter -racReader) : ()
, qw(-racActor -racManager -racPrincipal -racUser))
: ()) {
next if !exists($om->{$k}) && !exists($s->{$k});
my $td =&$cf($om, $om->{$k} ||$s->{$k});
$td .=($hl->{$k} && $hl->{$k}->[1]
? ' - ' .$s->htmlEscape($hl->{$k}->[1])
: '') if $td;
push @td, $td if $td;
}
$s->output("",$td1,$th,'',$td2,join(" \n$td1$td2", @td)," \n")
if @td;
($th, @td) =($s->htmlEscape(&$cl('-query'))); # no -frmLso -frmLsoAdd
foreach my $k (qw(-query)
) {
next if !exists($om->{$k}) && !exists($s->{$k});
my $td =$cfs
.$s->htmlEscape(&$cv(exists($om->{$k}) ? $om->{$k} : $s->{$k}))
.$cfe;
push @td, $s->lng(1,$k) .':', $td if $td;
my @td1 =map {$_ eq 'all'
? ()
: $s->htmlEscape($s->strquot($s->lng(0,$_))
# .($s->lng(1,$_) ? ' - ' .$s->lng(1,$_) : '')
)
} $s->mdeRoles($mt)
if $td;
push @td, &$cl('-frmLso')
. ': ' .join(', ', @td1)
if @td && @td1
}
$s->output("",$td1,$th,'',$td2,join(" \n$td1$td2", @td)," \n")
if @td;
($th, @td) =($s->htmlEscape(&$cl('-frmLsc')));
foreach my $k (qw(-frmLsc)
) {
next if !exists($om->{$k}) && !exists($s->{$k});
my $td =join(' '
, map { my ($e, $el, $ec) =$_;
if (ref($e) eq 'HASH') {
$el =$s->htmlEscape($s->lngslot($e,'-lbl'))
|| $e->{-val}
&& &$cf($om,$e->{-val});
$ec =$s->htmlEscape($s->lngslot($e,'-cmt'))
|| $e->{-val}
&& &$cf($om,$e->{-val},1);
}
elsif (ref($e) eq 'ARRAY') {
$el =$s->htmlEscape($e->[1]) ||&$cf($om,$e->[0]);
$ec =&$cf($om,$e->[0],1);
}
$el && $ec ? $el .' - ' .$ec
: $el ? $el
: ()
} @{$om->{$k}});
push @td, $td if $td;
}
$s->output("",$td1,$th,'',$td2,join(" \n$td1$td2", @td)," \n")
if @td;
if ($om->{-field} && (ref($om->{-field}) eq 'ARRAY')) {
foreach my $f (@{$om->{-field}}) {
next if ref($f) ne 'HASH';
$s->output(""
,$th2
,$s->htmlEscape($s->lnglbl($f) ||($f->{-fld} && $s->lng(0,$f->{-fld})) ||'')
,''
,$td2
,&$ce($s->lngcmt($f) ||($f->{-fld} && $s->lng(1,$f->{-fld})) ||'')
," \n"
);
$s->output(""
,$th2
,''
,$td2
,&$ce($s->lngslot($f,'-help')||'')
," \n"
) if $s->lngslot($f,'-help');
$th =join(' '
, $f->{-fld} ? $s->htmlEscape(&$cv($f->{-fld})) : ()
, $f->{-flg} ? $s->htmlEscape("(" .&$cff($f->{-flg}) .")") : ()
);
$th =join('; '
, $th ? $th : ()
, map { !exists($f->{$_})
? ()
: $s->htmlEscape($_ .'=> ' .&$cv($f->{$_}))
} qw(-expr -null -edit -hide -hidel -inp -ddlb -ddlbmult -ddlbtgt)
);
$s->output("",$th2,'',$td2,$cfs,$th,"$cfe \n")
if $th;
}
}
}
$s->output("\n
\n");
$s
}
sub cgiFooter { # Footer of CGI screen
my ($s) =@_;
my $cs =($s->{-c}->{-htmlclass} ? $s->htmlEscape($s->{-c}->{-htmlclass}) .' ' : '')
.'FooterArea';
return(undef) if $s->{-pcmd}->{-xml} ||$s->{-pcmd}->{-print};
if ($s->{-cgi} && $s->{-cgi}->{'.cgi_error'}
&& (($s->{-c}->{'.cgi_error'} ||'') ne $s->{-cgi}->{'.cgi_error'})) {
$_[0]->logRec('error','CGI', $s->{-cgi}->{'.cgi_error'})
}
# $s->logRec('***','perl'
# ,$]
# ,'@INC',@INC
# # , 'Win32::LoginName', Win32::LoginName()
# );
# $s->logRec('***','%ENV'
# ,map {($_, (defined($ENV{$_}) ? $ENV{$_} : 'undef'))
# } qw(SERVER_SOFTWARE SERVER_PROTOCOL GATEWAY_INTERFACE PERLXS SCRIPT_NAME PATH_INFO PATH_TRANSLATED REQUEST_METHOD REQUEST_URI QUERY_STRING REDIRECT_QUERY_STRING CONTENT_TYPE CONTENT_LENGTH));
# $s->logRec('***','CGI'
# ,(map { my $v =eval("\$CGI::$_");
# ("\$$_", defined($v) ? $v : 'undef')
# } qw (VERSION TAINTED MOD_PERL XHTML NOSTICKY NPH PRIVATE_TEMPFILES TABINDEX CLOSE_UPLOAD_FILES POST_MAX HEADERS_ONCE USE_PARAM_SEMICOLONS))
# ,(map { my $v =$s->url(!$_ ? () : ($_=>1));
# (($_||'%url'), (defined($v) ? $v : 'undef'))
# } '', qw(-absolute -relative -base))
# # ,'-self_url', ($s->cgi->self_url()||'')
# );
# if ($s->{-cgi} && $s->{-cgi}->{dbix_web}) {
# foreach my $v (split /[\n\r]+/, $s->{-cgi}->{dbix_web}) {
# $_[0]->logRec('***','CGI','dbix_web',$v)
# }
# }
# $s->logRec('***','param'
# ,map {($_, (defined($s->cgi->param($_)) ? $s->cgi->param($_) : 'undef'))
# } $s->cgi->param);
$s->output("\n"
,''
,' '
,"\n"
,($s->cgiHook('recList') && defined($s->{-fetched})
? ('',$s->{-limited} && ($s->{-limited} <=$s->{-fetched})
?($s->{-limited}, ' / ?')
:($s->{-fetched}||0)
,' ', $s->lng(1, '-fetched')," \n")
: defined($s->{-affected})
? ('',$s->{-affected}||0, ' ', $s->lng(1, '-affected')," \n")
: ())
," \n"
,'\n");
}
#########################################################
# Templates or Default Data Definitions
#########################################################
sub tn { # Template Naming
# (self, metaname) -> name
(($#_ <1) && $_[0]->{-tn})
|| ($_[0]->{-tn}->{$_[1]})
|| (substr($_[1],0,1) eq '-' ? substr($_[1],1) : $_[1])
}
sub tfoShow { # Template Field Option '-lblhtml' to Show all details absent
# (self, ? input name, ? [detail fields], ? html pattern)
my ($s, $n, $d, $h) =@_;
sub{ my $x =!$h ? '$_' : ref($h) eq 'CODE' ? &$h(@_) : $h;
$_[3]
|| $_[0]->{-pdta}->{$n||'tfoShow_'}
|| ($d && !(grep {!$_[0]->{-pout}->{$_}} @$d))
? $x
: ($x
.' ')
}
}
sub tfoHide { # Template Field Option '-hide' details absent
# (self, ? input name)
my ($s, $n) =@_;
sub {!($_ || $_[0]->{-pdta}->{$n||'tfoShow_'} ||$_[3])}
}
sub tfdRFD { # Template Field Definition for Record File Directory
# self, ? definition
my ($s) =@_; return
{-fld=>''
,-flg=>'e' # 'e'dit
,-lbl=>sub{$_[0]->lng(0,'rfafolder')}
,-cmt=>sub{$_[0]->lng(1,'rfafolder')}
,-lblhtml=> sub {
return('') if !$s->{-pout}->{-file};
'cgi->user_agent('MSIE')
? ' style="behavior:url(\'#default#httpFolder\')"'
: '')
.'>'
.($s->{-icons} && $IMG->{'rfafolder'}
? ' cgi->user_agent('MSIE')
? ' style="behavior:url(\'#default#httpFolder\')"'
: '')
.'/> '
: $s->htmlEscape($s->lng(0,'rfafolder')) .': ');
}
,-inp=>{-rfd=>1}
,@_ > 1 ? @_[1..$#_] : ()
}
}
sub ttoRVC { # Template Table Option for Record Version Control
my $s =$_[0];
my $tn=$s->{-tn};
(-key => $tn->{-key}
,-rvcInsBy => $tn->{-rvcInsBy}
,-rvcInsWhen => $tn->{-rvcInsWhen}
,-rvcUpdBy => $tn->{-rvcUpdBy}
,-rvcUpdWhen => $tn->{-rvcUpdWhen}
,-rvcActPtr => $tn->{-rvcActPtr}
,-rvcVerWhen => $tn->{-rvcVerWhen}
,-rvcChgState => $tn->{-rvcChgState}
,-rvcCkoState => $tn->{-rvcCkoState}
,-rvcDelState => $tn->{-rvcDelState}
,@_ > 1 ? @_[1..$#_] : ())
}
sub tvmVersions { # Template for Materialized View of Versions of records
# 'versions' materialized view default definition
# self, ? fields add, ? definitions add
my $s =$_[0];
my $tn=$s->{-tn};
return($tn->{'tvmVersions'}=>
{-lbl => sub{$_[0]->lng(0,'tvmVersions')}
,-cmt => sub{$_[0]->lng(1,'tvmVersions')}
,-field => [
{-fld=>'table', -edit=>0, -flg=>'uql'}
,{-fld=>$tn->{-rvcActPtr}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>'id', -edit=>0, -flg=>'uql'}
,{-fld=>$tn->{-rvcInsWhen}, -edit=>0, -flg=>'uq'}
,''
,{-fld=>$tn->{-rvcInsBy}, -edit=>0, -flg=>'uq'}
,{-fld=>$tn->{-rvcUpdWhen}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>$tn->{-rvcUpdBy}, -edit=>0, -flg=>'uql'}
,{-fld=>$tn->{-rvcState}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>'subject', -edit=>0, -flg=>'uql'}
,{-fld=>'readers', -edit=>0, -flg=>'u'}
,{-fld=>'cargo', -edit=>0, -flg=>'u'}
,ref($_[1]) eq 'ARRAY' ? @{$_[1]} : ()
]
,-key => ['table',$tn->{-rvcActPtr},'id']
,-racReader=> ['readers']
,-rvcInsBy=> $tn->{-rvcInsBy}
,-rvcUpdBy=> $tn->{-rvcUpdBy}
,-rvcActPtr=> $tn->{-rvcActPtr}
,-query => {-version=>'+'}
,-ixcnd => sub{$_[2]->{'id'}}
,-ixrec => sub{my $m =$_[0]->{-table}->{$_[1]->{-table}};
return(
{'table' =>$_[1]->{-table}
,$tn->{-rvcActPtr} =>$m->{-rvcActPtr} && $_[2]->{$m->{-rvcActPtr}}
,'id' =>$_[2]->{'id'}
,$tn->{-rvcInsWhen} =>$m->{-rvcInsWhen} && $_[2]->{$m->{-rvcInsWhen}}
,$tn->{-rvcInsBy} =>$m->{-rvcInsBy} && $_[2]->{$m->{-rvcInsBy}}
,$tn->{-rvcUpdWhen} =>$m->{-rvcUpdWhen} && $_[2]->{$m->{-rvcUpdWhen}}
,$tn->{-rvcUpdBy} =>$m->{-rvcUpdBy} && $_[2]->{$m->{-rvcUpdBy}}
,$tn->{-rvcState} =>$m->{-rvcChgState}&& $_[2]->{$m->{-rvcChgState}->[0]}
,'subject' =>mdeSubj($_[0],$_[2])
,'readers' =>join(',', map {$_[2]->{$_}||''}
grep {$_[2]->{$_}}
@{$m->{-racReader}||$_[0]->{-racReader}||[]}
, @{$m->{-racWriter}||$_[0]->{-racWriter}||[]})
,'cargo' =>join("\t",map {$_[2]->{$_}||''}
grep {$_[2]->{$_}} keys %{$_[2]})
})}
,-qhref => {-formfld =>'table'
,-key =>['id'] # [['id'=>2]]
}
,@_ > 2 ? @_[2..$#_] : ()
})
}
sub tfvVersions { # Template for Field View of Versions of records
my ($s, $f, @a) =@_; # (self, ? fields add, ? definitions add | sub{}(self, table, definitions add))
sub{
return('') if ($_[0]->{-pcmd}->{-cmg} eq 'recQBF')
|| !$_[0]->{-pcmd}->{-table}
|| !$_[0]->{-pout}->{'id'}
|| $_[0]->{-pcmd}->{-print};
my $v =$_[0]->{-tn}->{'tvmVersions'};
my $q =($_[0]->{-table}->{$_[0]->{-pcmd}->{-table}}->{-dbd} ||$_[0]->{-dbd}) eq 'dbi';
$v =$_[0]->{-pcmd}->{-table} if $q;
my @o =ref($a[0]) eq 'CODE' ? &{$a[0]}($_[0], $v, @a[1..$#a]) : @a;
my $u= $q
? {-key=>{$_[0]->{-tn}->{-rvcActPtr}=>$_[0]->{-pout}->{'id'}}
,-version=>1}
: {-key=>{$q
? ()
: ('table'=>$_[0]->{-pcmd}->{-table})
, $_[0]->{-tn}->{-rvcActPtr}=>$_[0]->{-pout}->{'id'}}
,-order=>'-deq'
,-version=>1};
my $h = $u
?($_[0]->cgi->hr()
. $_[0]->cgi->a({-title=>$_[0]->lng(1,'recQBF')
,-href=>$_[0]->urlCmd('',-cmd=>'recList'
,-form=>$v
,map { /^-/
? ('-q' .$' => $u->{$_})
: ()
} keys %$u)}
,$_[0]->lng(0,'tvmVersions') .':') .' ')
: $_[0]->cgi->hr();
local $_[0]->{-uiclass} ='tfvVersions';
local $_[0]->{-uistyle} ='font-size: small' if 0;
$_[0]->cgiList('-!h'
,$v
,undef
,{-qhrcol=>1, -qflghtml=>$h, $_[0]->shiftkeys(\@o,'-qhrcol|-qflghtml')}
,{$u ? %$u : ()
,-table=>$v
,-order=>$q ? $_[0]->{-tn}->{-rvcUpdWhen} . ' desc' : '-deq'
,-version=>1
,-data=>[$q
?('id', $_[0]->{-tn}->{-rvcUpdBy}, $_[0]->{-tn}->{-rvcUpdWhen})
:({-fld=>'table', -flg=>'q'}
,{-fld=>'id', -flg=>'q'}
,{-fld=>$_[0]->{-tn}->{-rvcUpdBy}, -flg=>'ql'}
,{-fld=>$_[0]->{-tn}->{-rvcUpdWhen}, -flg=>'ql'})
,ref($f) eq 'ARRAY' ? @$f : ()]
,-display=>[$_[0]->{-tn}->{-rvcUpdBy}, $_[0]->{-tn}->{-rvcUpdWhen}]
,@o
},'; ');
''
}
}
sub tvmHistory { # Template for Materialized View of database History
# 'history' materialized view default definition
# self, ? fields add, ? definitions add
my $s =$_[0];
my $tn=$s->{-tn};
return($tn->{'tvmHistory'}=>
{-lbl => sub{$_[0]->lng(0,'tvmHistory')}
,-cmt => sub{$_[0]->lng(1,'tvmHistory')}
,-field => [
{-fld=>$tn->{-rvcInsWhen}, -edit=>0, -flg=>'uq'}
,''
,{-fld=>$tn->{-rvcInsBy}, -edit=>0, -flg=>'uq'}
,{-fld=>$tn->{-rvcUpdWhen}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>$tn->{-rvcUpdBy}, -edit=>0, -flg=>'uql'}
# ,{-fld=>'table', -edit=>0, -flg=>'uq'}
# ,''
,{-fld=>'id', -edit=>0, -flg=>'uq'}
,{-fld=>$tn->{-rvcState}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>$tn->{-rvcActPtr}, -edit=>0, -flg=>'uq'}
,{-fld=>'subject', -edit=>0, -flg=>'uql'}
,{-fld=>'auser', -edit=>0, -flg=>'uql'}
,''
,{-fld=>'arole', -edit=>0, -flg=>'uql'}
,{-fld=>'puser', -edit=>0, -flg=>'uq'}
,''
,{-fld=>'prole', -edit=>0, -flg=>'uq'}
,{-fld=>'readers', -edit=>0, -flg=>'u'}
,{-fld=>'cargo', -edit=>0, -flg=>'u'}
,ref($_[1]) eq 'ARRAY' ? @{$_[1]} : ()
]
,-key => [$tn->{-rvcUpdWhen},$tn->{-rvcUpdBy},'id']
# ,'table'
,-racReader=> ['readers']
,-racPrincipal=>['puser','prole']
,-racActor=> ['auser','arole']
,-rvcInsBy=> $tn->{-rvcInsBy}
,-rvcUpdBy=> $tn->{-rvcUpdBy}
,-rvcActPtr=> $tn->{-rvcActPtr}
,-ixcnd => sub{$_[2]->{'id'} && $_[2]->{$tn->{-rvcUpdWhen}}}
,-ixrec => sub{
my $m =$_[0]->{-table}->{$_[1]->{-table}};
my $ra = mdeRole($_[0], $m, 'authors');
my $rp = mdeRole($_[0], $m, 'principals','users');
return(
{'id' =>$_[1]->{-table} .$RISM1 .$_[2]->{'id'}
#'table' =>$_[1]->{-table}
#'id' =>$_[2]->{'id'}
,$tn->{-rvcInsWhen} =>$m->{-rvcInsWhen} && $_[2]->{$m->{-rvcInsWhen}}
,$tn->{-rvcInsBy} =>$m->{-rvcInsBy} && $_[2]->{$m->{-rvcInsBy}}
,$tn->{-rvcUpdWhen} =>$m->{-rvcUpdWhen} && $_[2]->{$m->{-rvcUpdWhen}}
,$tn->{-rvcUpdBy} =>$m->{-rvcUpdBy} && $_[2]->{$m->{-rvcUpdBy}}
,$tn->{-rvcState} =>$m->{-rvcChgState}&& $_[2]->{$m->{-rvcChgState}->[0]}
,$tn->{-rvcActPtr} =>$m->{-rvcActPtr} && $_[2]->{$m->{-rvcActPtr}}
,'subject' =>mdeSubj($_[0],$_[2])
,'auser' =>(!$ra ? undef
: !ref($ra) ? $_[2]->{$ra}
: @$ra && $ra->[0] ? $_[2]->{$ra->[0]}
: undef)
|| $_[2]->{$m->{-rvcUpdBy} ||$_[0]->{-rvcUpdBy} ||''}
,'arole' =>!ref($ra) || $#$ra <1
? undef
: join(',', map {!$_[2]->{$_} ? () : ($_[2]->{$_})
} @$ra[1..$#$ra])
,'puser' =>(!$rp ? undef
: !ref($rp) ? $_[2]->{$rp}
: @$rp && $rp->[0] ? $_[2]->{$rp->[0]}
: undef)
|| $_[2]->{$m->{-rvcInsBy} ||$_[0]->{-rvcInsBy} ||''}
,'prole' =>!ref($rp) || $#$rp <1
? undef
: join(',', map {!$_[2]->{$_} ? () : ($_[2]->{$_})
} @$rp[1..$#$rp])
,'readers' =>join(',', map {$_[2]->{$_}||''}
grep {$_[2]->{$_}}
@{$m->{-racReader}||$_[0]->{-racReader}||[]}
, @{$m->{-racWriter}||$_[0]->{-racWriter}||[]})
,'cargo' =>join("\t",map {$_[2]->{$_}||''}
grep {$_[2]->{$_}} keys %{$_[2]})
})}
,-qhref => {-formfld =>'' # 'table'
,-key =>'id' # ['id'] # [['id'=>3]]
}
,-query => {-order =>'-dall'}
,@_ > 2 ? @_[2..$#_] : ()
})
}
sub tvmReferences { # Template for Materialized View of References to records
# 'references' materialized view default definition
# self, ? fields, ? definition
my $s =$_[0];
my $tn=$s->{-tn};
return ($tn->{'tvmReferences'}=>
{-lbl => sub{$_[0]->lng(0,'tvmReferences')}
,-cmt => sub{$_[0]->lng(1,'tvmReferences')}
,-field => [
{-fld=>'ir', -edit=>0, -flg=>'uql'}
,''
,{-fld=>'id', -edit=>0, -flg=>'uql'}
,{-fld=>$tn->{-rvcInsWhen}, -edit=>0, -flg=>'uq'}
,''
,{-fld=>$tn->{-rvcInsBy}, -edit=>0, -flg=>'uq'}
,{-fld=>$tn->{-rvcUpdWhen}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>$tn->{-rvcUpdBy}, -edit=>0, -flg=>'uq'}
,{-fld=>$tn->{-rvcState}, -edit=>0, -flg=>'uql'}
,''
,{-fld=>$tn->{-rvcActPtr}, -edit=>0, -flg=>'uq'}
,{-fld=>'subject', -edit=>0, -flg=>'uql'}
,{-fld=>'auser', -edit=>0, -flg=>'uql'}
,''
,{-fld=>'arole', -edit=>0, -flg=>'uql'}
,{-fld=>'puser', -edit=>0, -flg=>'uq'}
,''
,{-fld=>'prole', -edit=>0, -flg=>'uq'}
,{-fld=>'readers', -edit=>0, -flg=>'u'}
,ref($_[1]) eq 'ARRAY' ? @{$_[1]} : ()
]
,-key => ['ir',$tn->{-rvcUpdWhen},'id']
,-qhrcol=> 1
,-racReader=> ['readers']
,-racPrincipal=>['puser','prole']
,-racActor=> ['auser','arole']
,-rvcInsBy=> $tn->{-rvcInsBy}
,-rvcUpdBy=> $tn->{-rvcUpdBy}
,-rvcActPtr=> $tn->{-rvcActPtr}
,-ixcnd => sub{$_[2]->{'id'}
&& ($_[0]->{-table}->{$_[1]->{-table}}->{-ridRef}
||$_[0]->{-ridRef})}
,-ixrec => sub{
my $s =$_[0];
my $m =$s->{-table}->{$_[1]->{-table}};
my $ir =[];
my $id =$_[1]->{-table} .$RISM1 .$_[2]->{'id'};
foreach my $f (@{$m->{-ridRef} ||$s->{-ridRef}}) {
if (!$_[2]->{$f}) {
next
}
elsif ($_[2]->{$f} =~/[\s,.?]/) {
my $v =$_[2]->{$f};
while ($v =~/(?:_key=id%3D|_key=)([\w\d]+\Q$RISM1\E[\w\d]+)/i) {
push @$ir, $1;
$v =$'
}
}
elsif (length($_[2]->{$f}) >$NLEN *3) {
next
}
elsif ($_[2]->{$f} =~/\Q$RISM1\E/) {
push @$ir, $_[2]->{$f}
}
else {
push @$ir, $_[1]->{-table} .$RISM1 .$_[2]->{$f}
}
}
return($ir) if !@$ir;
my $ra = mdeRole($_[0], $m, 'authors');
my $rp = mdeRole($_[0], $m, 'principals','users');
my $rv =
{'id' =>$id
# below alike 'tvmHistory'
,$tn->{-rvcInsWhen} =>$m->{-rvcInsWhen} && $_[2]->{$m->{-rvcInsWhen}}
,$tn->{-rvcInsBy} =>$m->{-rvcInsBy} && $_[2]->{$m->{-rvcInsBy}}
,$tn->{-rvcUpdWhen} =>$m->{-rvcUpdWhen} && $_[2]->{$m->{-rvcUpdWhen}}
,$tn->{-rvcUpdBy} =>$m->{-rvcUpdBy} && $_[2]->{$m->{-rvcUpdBy}}
,$tn->{-rvcState} =>$m->{-rvcChgState}&& $_[2]->{$m->{-rvcChgState}->[0]}
,$tn->{-rvcActPtr} =>$m->{-rvcActPtr} && $_[2]->{$m->{-rvcActPtr}}
,'subject' =>mdeSubj($_[0],$_[2])
,'auser' =>(!$ra ? undef
: !ref($ra) ? $_[2]->{$ra}
: @$ra && $ra->[0] ? $_[2]->{$ra->[0]}
: undef)
|| $_[2]->{$m->{-rvcUpdBy} ||$_[0]->{-rvcUpdBy} ||''}
,'arole' =>!ref($ra) || $#$ra <1
? undef
: join(',', map {!$_[2]->{$_} ? () : ($_[2]->{$_})
} @$ra[1..$#$ra])
,'puser' =>(!$rp ? undef
: !ref($rp) ? $_[2]->{$rp}
: @$rp && $rp->[0] ? $_[2]->{$rp->[0]}
: undef)
|| $_[2]->{$m->{-rvcInsBy} ||$_[0]->{-rvcInsBy} ||''}
,'prole' =>!ref($rp) || $#$rp <1
? undef
: join(',', map {!$_[2]->{$_} ? () : ($_[2]->{$_})
} @$rp[1..$#$rp])
,'readers' =>join(',', map {$_[2]->{$_}||''}
grep {$_[2]->{$_}}
@{$m->{-racReader}||$s->{-racReader}||[]}
, @{$m->{-racWriter}||$s->{-racWriter}||[]})
};
map {$_ ={'ir'=>$_, %$rv}} @$ir;
$ir}
,-qhref => {-formfld =>''
,-key =>'id'
}
,-query => {-order =>'-dall'}
,@_ > 2 ? @_[2..$#_] : ()
})
}
sub tfvReferences { # Template for Field embedded View of References to record
my ($s, $f, @a) =@_; # (self, ? fields add, ? definitions add | sub{}(self, table, definitions add))
sub{
return('')
if ($_[0]->{-pcmd}->{-cmg} eq 'recQBF')
|| !$_[0]->{-pcmd}->{-table}
|| !$_[0]->{-pout}->{'id'};
my $v =$_[0]->{-tn}->{'tvmReferences'};
my $q =(($_[0]->{-table}->{$_[0]->{-pcmd}->{-table}}->{-dbd} ||$_[0]->{-dbd})
eq 'dbi')
&& !$_[0]->{-table}->{$v};
$v =$_[0]->{-pcmd}->{-table} if $q;
my @o =ref($a[0]) eq 'CODE' ? &{$a[0]}($_[0], $v, @a[1..$#a]) : @a;
my $qe =$_[0]->{-pout}->{comment} && $_[0]->{-table}->{$v} && $_[0]->{-table}->{$v}->{-mdefld} && $_[0]->{-table}->{$v}->{-mdefld}->{comment};
$qe =$qe && $qe->{-inp} && ($qe->{-inp}->{-htmlopt} || $qe->{-inp}->{-hrefs})
&& $_[0]->{-pout}->{comment};
$qe =$qe && ($qe =~/^<(?:where|qwhere)>(.+?)<\/(?:where|qwhere)>/i) && $1;
return('')
if $q
? !$_[0]->{-table}->{$v}->{-ridRef}
: !$_[0]->{-table}->{$v};
my $u =$q
? {-where=>join(' OR '
, $qe ? "($qe)" : ()
, map { $v .'.' .$_ .'=' .$_[0]->dbi->quote($_[0]->{-pout}->{'id'})
} @{$_[0]->{-table}->{$v}->{-ridRef}}
)}
: {-key=>{'ir'=>$_[0]->{-pcmd}->{-table} .$RISM1 .$_[0]->{-pout}->{'id'}}
,-order=>'-deq'
};
my $h = $_[0]->{-pcmd}->{-print}
? $_[0]->cgi->hr()
: $u
?($_[0]->cgi->hr()
#. ''
. $_[0]->cgi->a({-title=>$_[0]->lng(1,'recQBF')
,-href=>$_[0]->urlCmd('',-cmd=>'recList'
,-form=>$v
,map { /^-/
? ('-q' .$' => $u->{$_})
: ()
} keys %$u)}
,$_[0]->lng(0,'tvmReferences') .':'))
#. '
'
: $_[0]->cgi->hr();
local $_[0]->{-uiclass} ='tfvReferences';
local $_[0]->{-uistyle} ='font-size: small' if 0;
$_[0]->cgiList('-!h'
,$v
,undef
,{-qhrcol=>0, -qflghtml=>$h, $_[0]->shiftkeys(\@o,'-qhrcol|-qflghtml')}
,{$u ? %$u : ()
,-table=>$v
,-version=>0
, $q
?(
(map {$_[0]->{-table}->{$v}->{-query} && $_[0]->{-table}->{$v}->{-query}->{$_}
? ($_ => $_[0]->{-table}->{$v}->{-query}->{$_})
: ()
} qw (-display -data -datainc -order -keyord))
# ,-order=>$_[0]->{-tn}->{-rvcUpdWhen}
# ,-keyord=>'-dall'
,$_[0]->shiftkeys(\@o,'-display|-data|-datainc|-where|-key|-order|-keyord')
)
:(-field=>[{-fld=>'ir', -flg=>'q'}
,{-fld=>'id', -flg=>'q'}
,{-fld=>$_[0]->{-tn}->{-rvcUpdWhen}, -flg=>'ql'}
,{-fld=>$_[0]->{-tn}->{-rvcState}, -flg=>'ql'}
,{-fld=>'subject', -flg=>'ql'}
,{-fld=>'auser', -flg=>'ql'}
,{-fld=>'arole', -flg=>'ql'}
,ref($f) eq 'ARRAY' ? @$f : ()
]
,-order=>'-deq'
)
,@o
});
''
}
}
sub tvdIndex { # Template View Definition for Index page
my $s =$_[0]; return ($s->{-tn}->{'tvdIndex'}=>
{-lbl =>sub{$_[0]->lng(0,'tvdIndex')}
,-cmt =>sub{$_[0]->lng(1,'tvdIndex')}
,-cgcCall =>sub{
my $s =$_[0];
$s->{-fetched} =undef;
$s->{-affected} =undef;
local @{$s}{-menuchs, -menuchs1} =@{$s}{-menuchs, -menuchs1};
$s->htmlMChs() if !$s->{-menuchs};
$s->output($s->htmlStart(@_[1,2]) # HTTP/HTML/Form headers
,$s->htmlHidden(@_[1,2]) # common hidden fields
,!$s->{-pcmd}->{-print}
&& $s->htmlMenu(@_[1,2]) # Menu bar
,"\n\n"
);
$s->htmlOnLoad("{var e=document.getElementsByTagName('BASE'); if(e && e[0] && (self.name.match(/^(?:TOP|BOTTOM)\$/) || document.getElementsByName('_frame').length)){e[0].target='_blank'}}");
foreach my $e (($s->{-menuchs} ? @{$s->{-menuchs}} : ())
,($s->{-menuchs1}? @{$s->{-menuchs1}}: ())
) {
my ($n, $l) = ref($e) ? @$e : ($e, $e);
$l ='--- ' .$_[0]->lng(0, 'frmCallNew') .' ---' if !$n && !$l;
next if $n eq '-frame';
my ($o, $a) = $n =~/^(.+?)([+&.]+)$/ ? ($1, $2) : ($n, $n);
my $l0 =$s->lnglbl($s->{-form}->{$o} ||$s->{-table}->{$o} ||{}, $o)||'';
my $l1 =$s->lngcmt($s->{-form}->{$o} ||$s->{-table}->{$o} ||{}, $o)||'';
my $ur1=$s->urlCat('','_form'=>$n,'_cmd'=>'frmCall');
my $ur2=$s->{-pcmd}->{-frame}
? $s->urlCat('','_form'=>$n,'_cmd'=>'frmCall','_frame'=>$s->{-pcmd}->{-frame})
: $ur1;
$s->output(''
, $n
? $s->cgi->a({-href=>$ur1
,-title=> $a =~/[+]/
? $s->lng(1,'frmCallNew') ." '$l0'"
: $a =~/[&.]/
? $s->lng(0,'frmCallOpn') ." '$l0'"
: $s->lng(0,'frmCallOpn') ." '$l0'"
, $a =~/[+]/ # form
? (-OnClick=>"window.document.open('$ur1', self.name.match(/^(?:TOP|BOTTOM)\$/) || document.getElementsByName('_frame').length ? '_blank' : '_self','',false); return(false)"
# or "this.target = self.name.match(/^(?:TOP|BOTTOM)\$/) || document.getElementsByName('_frame').length ? '_blank' : '_self'; return(true)";
)
: (-target=>'_self' # list
,-OnClick=>"window.document.open('$ur2', self.name=='TOP' ? '_self': self.name=='BOTTOM' ? 'TOP' : '_self','',false); return(false)"
# or "this.target = self.name=='TOP' ? '_self' : self.name=='BOTTOM' ? 'TOP' : '_self'; return(true)";
)
}
,(!$s->{-icons}
? ''
: ' ')
. $s->htmlEscape($l0))
: $s->htmlEscape($l)
, " \n"
, ' '
, $s->htmlEscape( !$l1 || $l1 ne $l0
? $l1||''
: 1
? $l1||''
: $a =~/[+]/
? $s->lng(0,'frmCallNew') ." '$l0'"
: $a =~/[&.]/
? $s->lng(0,'frmCallOpn') ." '$l0'"
: $s->lng(0,'frmCallOpn') ." '$l0'"
)
, " \n"
)
}
$s->output("\n
\n");
# $s->recCommit();
$s->cgiFooter() if !$s->{-pcmd}->{-print};
$s->output($s->htmlEnd());
$s->end();
}
,@_ > 1 ? @_[1..$#_] : ()
})
}
sub tvdFTQuery { # Template View Definition for Full-Text Query
my $s =$_[0]; return ($s->{-tn}->{'tvdFTQuery'}=>
{-lbl =>sub{$_[0]->lng(0,'tvdFTQuery')}
,-cmt =>sub{$_[0]->lng(1,'tvdFTQuery')}
,-cgcCall =>sub{
my $s =$_[0];
my $g =$s->cgi();
$s->{-fetched} =0;
$s->{-affected} =undef;
$s->{-pcmd}->{-cmd} =$s->{-pcmd}->{-cmg} ='recQBF';
$s->output($s->htmlStart(@_[1,2]) # HTTP/HTML/Form headers
,$s->htmlHidden(@_[1,2]) # common hidden fields
,!$s->{-pcmd}->{-print}
&& $s->htmlMenu(@_[1,2]) # Menu bar
,"\n"
);
$s->die('Microsoft IIS required') if $ENV{SERVER_SOFTWARE} !~/IIS/;
$g->param('_qftwhere'
, defined($g->param('_qftwhere')) && ($g->param('_qftwhere') ne '')
? $g->param('_qftwhere')
: defined($g->param('_qftext')) && ($g->param('_qftext') ne '')
? $g->param('_qftext')
: '');
$s->output($g->textfield(-name=>'_qftwhere', -size=>70, -title=>$s->lng(1,'-qftwhere'))
, ' '
, $g->popup_menu(-name=>'_qftord'
,-values=>['write','hitcount','vpath','docauthor']
,-labels=>{
'write' =>'Chronologically'
,'hitcount' =>'Ranked'
,'vpath' =>'by Name'
,'docauthor' =>'by Author'
}
,-default=>'write')
, $g->popup_menu(-name=>'_qlimit'
,-values=>['',128,256,512,1024,2048,4096]
,-labels=>{
'' =>"$LIMRS default"
,128 =>'128 max'
,256 =>'256 max'
,512 =>'512 max'
,1024=>'1024 max'
,2048=>'2048 max'
,4096=>'4096 max'
}
,-default=>$LIMRS)
, $g->submit(-name =>'tvdFTQuery_'
,-value=>$s->lng(0,'recList')
,-title=>$s->lng(1,'recList'))
, '' && $g->a({-href=>
-e ($ENV{windir} .'/help/ix/htm/ixqrylan.htm')
? '/help/microsoft/windows/ix/htm/ixqrylan.htm'
: '/help/microsoft/windows/isconcepts.chm' # .'::/ismain-concepts_30.htm'
}, '?')
, " \n");
if ($g->param('_qftwhere') ne '') {
eval('use Win32::OLE; Win32::OLE->Option("Warn"=>0)');
Win32::OLE->Initialize();
# Win32::OLE->Initialize(&Win32::OLE::COINIT_OLEINITIALIZE);
# Search MSDN for 'ixsso.Query'
my $oq =Win32::OLE->CreateObject("ixsso.Query");
!$oq && $s->die("'OLE->CreateObject(ixsso.Query)' failed '$!'/'$@'/" .Win32::OLE->LastError);
my $ou =Win32::OLE->CreateObject("ixsso.util");
!$oq && $s->die("'OLE->CreateObject(ixsso.util)' failed '$!'/'$@'/" .Win32::OLE->LastError);
my $qs =[];
my $qt =[];
$oq->{Query} =$g->param('_qftwhere') =~/^(@\w|\{\s*prop\s+name\s+=)/i
? $g->param('_qftwhere')
: ('@contents ' .$g->param('_qftwhere'));
$oq->{Catalog} ='Web';
$oq->{MaxRecords} =$g->param('_qlimit') ||$LIMRS;
$oq->{MaxRecords} =4096 if $oq->{MaxRecords} >4096;
$oq->{SortBy} =$g->param('_qftord') ||'write';
$oq->{SortBy} .=$oq->{SortBy} =~/^(write|hitcount)$/i
? '[d],docauthor[a]'
: '[a],write[d]';
$oq->{Columns} ='vpath,path,filename,hitcount,write,doctitle,docauthor,characterization';
$oq->{LocaleID} =1049; # ru
my $ol =eval {$oq->CreateRecordset('sequential')}; # 'nonsequential'
!$oq && $s->die("'OLE->CreateRecordset(sequential)' failed '$!'/'$@'/" .Win32::OLE->LastError);
$s->output('No records found') if $ol->{EOF};
my ($rcf, $rct, $rcd) =(0, 0, 0);
while (!$ol->{EOF}) {
my $vp =$ol->{vPath}->{Value};
$rcf +=1;
if (!$vp) {
$rct +=1;
}
if ($vp) {
$rcd +=1;
my $vt =$g->escapeHTML($ol->{DocTitle}->{Value});
$vt = ($vt ? '$vt' .' ' : '')
. '(' .$g->escapeHTML($ol->{DocAuthor}->{Value}) .')'
if $ol->{DocAuthor}->{Value};
$vt = ($vt ? $vt .' (' : '')
. $g->escapeHTML($vp) .')';
$s->output($g->a({-href=>$vp||$ol->{Path}->{Value}
,-title=>$ol->{HitCount}->{Value}
.': ' .$ol->{Path}->{Value}}
, $vt)
, $ol->{Characterization}->{Value}
? ' ' .$g->escapeHTML($ol->{Characterization}->{Value})
: ''
, " \n");
}
if (!eval {$ol->MoveNext; 1}) {
$s->output('Bad query');
last
}
}
Win32::OLE->FreeUnusedLibraries;
# Win32::OLE->Uninitialize;
$s->{-fetched} =$rcd;
$s->{-affected} =$rcf;
$s->logRec('FTQuery',-fetched=>$rcd, -found=>$rcf, -vpathgen=>$rct, -max=>($oq->{MaxRecords}||'undef'));
}
else {
$s->output('Enter query condition')
}
$s->{-pcmd}->{-cmd} =$s->{-pcmd}->{-cmg} ='recList';
$s->cgiFooter() if !$s->{-pcmd}->{-print};
$s->output($s->htmlEnd());
$s->end();
}
,@_ > 1 ? @_[1..$#_] : ()})
}
sub ttsAll { # Template Tables Set of All generally used views
return( # - to add to '-table'
$_[0]->tvmVersions()
,$_[0]->tvmHistory()
,$_[0]->tvmReferences()
)
}
sub tfsAll { # Template Fields Set for All generally used fields
return( # - to add to '-field'
$_[0]->tfdRFD()
,"\f"
,$_[0]->tfvVersions()
,$_[0]->tfvReferences()
)
}
#########################################################
# File Handle Object
#########################################################
package DBIx::Web::FileHandle;
use strict;
use Symbol;
use Fcntl qw(:DEFAULT :flock :seek :mode);
sub new {
my ($c, %o) =@_;
my $s ={-name =>'' # file name
,-mode =>'<' # file open mode
,-parent=>undef # parent object
,-handle=>undef # Symbol::gensym on file open
,-lock =>LOCK_UN # lock level
,-lcks =>{} # locks
# ,-new =>undef # new file created
# ,-buf =>undef # file contents from 'loadXX' calls
# ,-ret =>undef # data to return, for external programming
};
foreach my $k (keys(%o)) {$s->{$k} =$o{$k}}
bless $s, $c;
$s->open() if defined($s->{-name}) && $s->{-name} ne '';
$s
}
sub set {
return(keys(%{$_[0]})) if scalar(@_) ==1;
return($_[0]->{$_[1]}) if scalar(@_) ==2;
my ($s, %o) =@_;
foreach my $k (keys(%o)) {$s->{$k} =$o{$k}};
$s
}
sub parent {
$_[0]->{-parent}
}
sub open {
my $s =shift;
if (!@_) {}
elsif ($_[0] =~/^-(name|mode)$/) {$s->set(@_)}
else {foreach my $k ('-mode','-name') {$s->{$k} =shift if defined($_[0])}}
$s->{-new} =!-e $s->{-name};
$s->{-lcks}={};
if (!CORE::open($s->{-handle} =Symbol::gensym, $s->{-mode}, $s->{-name})) {
$s->{-handle} =undef;
return(&{$s->{-parent} ? $s->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("File: open('" .($s->{-mode}||'') ."','" .($s->{-name}||'') ."') -> $!"
.($s->{-parent} && $s->{-parent}->{-ermd} ||'')
) ||undef)
}
$s
}
sub opent {
return($_[0]) if $_[0]->{-handle};
$_[0]->open() || return(undef);
$_[0]->lock($_[0]->{-lock}) if $_[0]->{-lock} ne LOCK_UN;
$_[0]
}
sub binmode {
CORE::binmode($_[0]->{-handle}); $_[0]
}
sub close {
return($_[0]) if !$_[0]->{-handle};
$_[0]->lock(LOCK_UN |LOCK_NB) if $_[0]->{-lock} ne LOCK_UN;
$_[0]->{-lcks}={};
CORE::close($_[0]->{-handle});
$_[0]->{-handle} =undef;
$_[0]
}
sub destroy {
eval{$_[0]->close()} if $_[0]->{-handle};
$_[0]->{-parent} =undef;
$_[0]
}
sub DESTROY {
destroy(@_)
}
sub lock { # ?lock value, ?lock key
# LOCK_SH ==1; LOCK_EX ==2, or LOCK_UN ==8, LOCK_NB ==4
return($_[0]->{-lock}) if !defined($_[1]);
my $l =!$_[1] ? LOCK_UN : $_[1];
my $lv=$l | LOCK_NB ^ LOCK_NB;
$_[0]->opent() if !$_[0]->{-handle};
if ($_[0]->{-lock} ne $lv) {
if ($lv eq LOCK_UN) {
CORE::flock($_[0]->{-handle}, $_[0]->{-lock} =LOCK_UN);
if (!defined($_[2])) { $_[0]->{-lcks} ={} }
else { delete $_[0]->{-lcks}->{$_[2]} }
$l =0; map {$l =$_ if $l <$_} values %{$_[0]->{-lcks}};
$_[0]->{-lock} =$lv =$l if $l && CORE::flock($_[0]->{-handle}, $l);
}
else {
CORE::flock($_[0]->{-handle}, $_[0]->{-lock} =LOCK_UN);
$_[0]->{-lock} =$lv if CORE::flock($_[0]->{-handle}, $l);
}
}
if (!defined($_[2])) { $_[0]->{-lcks} ={} }
elsif ($lv eq LOCK_UN
|| $_[0]->{-lock} ne $lv ) { delete $_[0]->{-lcks}->{$_[2]} }
else { $_[0]->{-lcks}->{$_[2]} =$lv }
$_[0]->{-lock} eq $lv ? $_[0] : undef
}
sub seek {
# WHENCE: 0 - SEEK_SET - to set the new position to POSITION,
# 1 - SEEK_CUR - to set it to the current position plus POSITION,
# 2 - SEEK_END - to set it to EOF plus POSITION
return(CORE::tell($_[0]->{-handle})) if @_ <2;
CORE::seek($_[0]->{-handle}, $_[1], defined($_[2]) ?$_[2] :SEEK_SET)
? $_[0]
: (&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("File: seek('" .($_[0]->{-name}||'') ."') -> $!"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef)
}
sub read {
my $r =CORE::read($_[0]->{-handle}, $_[1], $_[2], $_[3]||0);
return(&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("File: read('" .($_[0]->{-name}||'') ."') -> $!"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef)
if !defined($r);
$r
}
sub readline {
CORE::readline($_[0]->{-handle})
}
sub print {
my $s =shift;
my $h =$s->{-handle};
return(&{$s->{-parent} ? $s->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("File: print('" .($s->{-name}||'') ."') -> $!"
.($s->{-parent} && $s->{-parent}->{-ermd} ||'')
) ||undef)
if !CORE::print $h @_;
$s
}
sub load {
my $b ='';
my $l =$_[0]->{-lock};
$_[0]->opent() if !$_[0]->{-handle};
$_[0]->lock(LOCK_SH) if $l eq LOCK_UN;
$_[0]->{-buf} =defined($_[0]->seek(0)->read($b, -s $_[0]->{-handle})) ? $b : undef;
$_[0]->lock(LOCK_UN) if $l eq LOCK_UN;
defined($_[0]->{-buf}) ? $_[0] : undef;
}
sub store {
my $s =shift;
my $l =$s->{-lock};
$s->opent() if !$s->{-handle};
$s->lock(LOCK_EX) if $l eq LOCK_UN;
$s->select(sub{$|=1});
my $r =$s->seek(0)->print(@_ ? @_ : $s->{-buf}); # !!! simple, may be unsafe
truncate($s->{-handle}, CORE::tell($s->{-handle}));
$s->lock(LOCK_UN) if $l eq LOCK_UN;
$r
}
sub select {
my $r;
ref($_[1]) eq 'CODE'
? select((select($_[0]->{-handle}), $r =&{$_[1]}(@_))[0]) && $r
: select($_[0]->{-handle})
}
#########################################################
# DB_File ISAM Handle Object
#########################################################
package DBIx::Web::dbmHandle;
use strict;
use Symbol;
use Fcntl qw(:DEFAULT :flock :seek :mode);
# my $NLEN =20; # length to pad left index numbers
sub new {
my ($c, %o) =@_;
my $s ={-name =>'' # file name
,-mode =>O_CREAT|O_RDWR
,-parent=>undef # parent object
#,-table =>undef # data table description
,-handle=>undef # tied object ref
#,-data =>undef # tied data hash ref
#,-new =>undef # new file created
#,-fh =>undef # file handle
,-lock =>LOCK_UN # lock level
,-lcks =>{} # locks
,-pair =>[] # current key/value
};
foreach my $k (keys(%o)) {$s->{$k} =$o{$k}}
bless $s, $c;
$s->open if defined($s->{-name}) && $s->{-name} ne '';
$s
}
sub set {
return(keys(%{$_[0]})) if scalar(@_) ==1;
return($_[0]->{$_[1]}) if scalar(@_) ==2;
my ($s, %o) =@_;
foreach my $k (keys(%o)) {$s->{$k} =$o{$k}};
$s
}
sub parent {
$_[0]->{-parent}
}
sub open {
eval('use DB_File');
my $s =shift;
if (!@_) {}
elsif ($_[0] =~/^-(name|mode)$/) {$s->set(@_)}
else {foreach my $k ('-mode','-name') {$s->{$k} =shift if defined($_[0])}}
my %hash;
my $par =eval('new DB_File::BTREEINFO');
if ($s->{-table} && $s->{-table}->{-keycmp}) {
my $t =$s->{-table}->{-keycmp};
$par->{'compare'} =sub{&t($s, map {[map {m/^ *(.*)$/ ? $1 : $_} split /\x00/, $_]} @_)}
# see keyUnescape below
}
$s->{-new} =!-e $s->{-name};
$s->{-handle} =tie %hash, 'DB_File', $s->{-name}, $s->{-mode}, 0x666, $par;
$s->{-data} =\%hash;
$s->{-lcks} ={};
if (!$s->{-handle}) {
$s->{-handle} =$s->{-data} =undef;
return(&{$s->{-parent} ? $s->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: open('" .($s->{-mode}||'') ."','" .($s->{-name}||'') ."') -> $!"
.($s->{-parent} && $s->{-parent}->{-ermd} ||'')
) ||undef)
}
$s
}
sub opent {
return($_[0]) if $_[0]->{-handle};
$_[0]->open || return(undef);
$_[0]->lock($_[0]->{-lock}) if $_[0]->{-lock} ne LOCK_UN;
$_[0]
}
sub close {
return($_[0]) if !$_[0]->{-handle};
$_[0]->lock(LOCK_UN) if $_[0]->{-lock} ne LOCK_UN;
close($_[0]->{-fh}) if $_[0]->{-fh};
my $h =$_[0]->{-data};
$_[0]->{-data} =undef;
$_[0]->{-handle} =undef;
$_[0]->{-fh} =undef;
$_[0]->{-lcks} ={};
#eval {untie %$h}; # warning if another reference exists
$_[0]
}
sub sync {
return($_[0]) if !$_[0]->{-handle};
$_[0]->{-handle}->sync();
}
sub destroy {
eval{$_[0]->close} if $_[0]->{-handle};
$_[0]->{-parent} =undef;
$_[0]->{-table} =undef;
$_[0]
}
sub DESTROY {
destroy(@_)
}
sub lock { # lock value, ?lock key
# LOCK_SH ==1; LOCK_EX ==2, or LOCK_UN ==8, LOCK_NB ==4
return($_[0]->{-lock}) if !defined($_[1]);
my $l =!$_[1] ? LOCK_UN : $_[1];
my $lv=$l | LOCK_NB ^ LOCK_NB;
if (!$_[0]->{-fh} && !CORE::open($_[0]->{-fh} =Symbol::gensym, '+<&=' .$_[0]->{-handle}->fd)) {
$_[0]->{-fh} =undef;
return(&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: open('+<&=','" .($_[0]->{-name}||'') ."') -> $!"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef)
}
if ($_[0]->{-lock} ne $lv) {
$_[0]->{-handle}->sync;
if ($lv eq LOCK_UN) {
CORE::flock($_[0]->{-fh}, $_[0]->{-lock} =LOCK_UN);
if (!defined($_[2])) { $_[0]->{-lcks} ={} }
else { delete $_[0]->{-lcks}->{$_[2]} }
$l =0; map {$l =$_ if $l <$_} values %{$_[0]->{-lcks}};
$_[0]->{-lock} =$lv =$l if $l && CORE::flock($_[0]->{-fh}, $l);
}
else {
CORE::flock($_[0]->{-fh}, $_[0]->{-lock} =LOCK_UN);
$_[0]->{-lock} =$lv if CORE::flock($_[0]->{-fh}, $l);
}
$_[0]->{-handle}->sync;
}
if (!defined($_[2])) { $_[0]->{-lcks} ={} }
elsif ($lv eq LOCK_UN
|| $_[0]->{-lock} ne $lv ) { delete $_[0]->{-lcks}->{$_[2]} }
else { $_[0]->{-lcks}->{$_[2]} =$lv }
$_[0]->{-lock} eq $lv ? $_[0] : undef
}
sub keyGet {
return($_[0]->{-pair}->[1]) if @_ <2;
my $v; $_[0]->{-handle}->get($_[1], $v) ? undef : $v
}
sub keyPut {
$_[0]->{-handle}->put($_[1], $_[$#_])
? (&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: keyPut('" .($_[0]->{-name}||'') ."','" .$_[1] ."') -> $!"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef)
: (@_ >3) && ($_[1] ne $_[2]) && $_[0]->{-handle}->del($_[2])
? (&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: keyDel('" .($_[0]->{-name}||'') ."','" .$_[2] ."') -> $!"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef)
: $_[$#_]
}
sub keyDel {
$_[0]->{-handle}->del(@_[1..$#_]) ? undef : $_[0]
}
sub keyFind {
my ($s, $k, $v) =@_;
$s->{-handle}->seq($k, $v, R_CURSOR()) ? undef : (@{$s->{-pair}}[1,0]=($k,$v))[0]
}
sub keyFirst {
my ($s, $k, $v) =@_;
$s->{-handle}->seq($k, $v, R_FIRST()) ? undef : (@{$s->{-pair}}[1,0]=($k,$v))[0]
}
sub keyLast {
my ($s, $k, $v) =@_;
$s->{-handle}->seq($k, $v, R_LAST()) ? undef : (@{$s->{-pair}}[1,0]=($k,$v))[0]
}
sub keyPrev {
my ($s, $k, $v) =@_;
$s->{-handle}->seq($k, $v, R_PREV()) ? undef : (@{$s->{-pair}}[1,0]=($k,$v))[0]
}
sub keyNext {
my ($s, $k, $v) =@_;
$s->{-handle}->seq($k, $v, R_NEXT()) ? undef : (@{$s->{-pair}}[1,0]=($k,$v))[0]
}
sub krEscape {
join "\x00"
,map { my $v =$_;
return('') if !defined($v); # !!! lost undefined values
$v =~s/^ *(.*?) *$/$1/; # !!! lost extra blanks
# $v =~s/\000/\\000/g; # !!! key compare problem
$v =~s/\000//g; # !!! lost \x00 chars
$v =' ' x ($NLEN -length($v)) .$v # !!! $NLEN-sign numbers
if $v =~/^[\d .,]+$/m && length($v) <$NLEN;
$v
} @{$_[1]}
}
sub krEscapeMv {
my $r =[''];
foreach my $v (@{$_[1]}) {
if (!ref($v)) {
$v ='' if !defined($v); # !!! lost undefined values
$v =~s/^ *(.*?) *$/$1/; # !!! lost extra blanks
$v =~s/\000//g; # !!! lost \x00 chars
$v =' ' x ($NLEN -length($v)) .$v # !!! $NLEN-sign numbers
if $v =~/^[\d .,]+$/m && length($v) <$NLEN;
map {$_ .=$v ."\x00"} @$r
}
elsif (ref($v) eq 'ARRAY') {
my $r0 =$r; $r =[];
my $a =$v;
foreach my $k (@$a) {
foreach my $e (@{krEscapeMv($_[0],$k)}) {
foreach my $v (@$r0) { push @$r, "$v$e\x00" }
}
}
}
elsif (ref($v) eq 'HASH') {
my $r0 =$r; $r =[];
my $h =$v;
foreach my $k (keys %$h) {
my $v =$k;
$v ='' if !defined($v); # !!! lost undefined values
$v =~s/^ *(.*?) *$/$1/; # !!! lost extra blanks
$v =~s/\000//g; # !!! lost \x00 chars
foreach my $e (@{krEscapeMv($_[0], $h->{$k})}) {
foreach my $v (@$r0) { push @$r, $v . "$k=>$e\x00" }
}
}
}
}
map {chop $_} @$r;
$r
}
sub krUnescape {
[map {m/^ *(.*)$/ ? $1 : $_} split /\x00/, $_[$#_]]
}
sub klUnescape {
map {m/^ *(.*)$/ ? $1 : $_} split /\x00/, $_[$#_]
}
sub hrEscape { # freeze($_[$#_])
ref($_[$#_]) ne 'ARRAY'
? '{' .join(','
, map { my ($k, $v) =($_, $_[$#_]->{$_});
$k =~s/([,=%\\\]\[\{\}])/sprintf("\\x%02x",ord($1))/eg;
if (ref($v)) {$v =hrEscape($v)}
else {$v =~s/([,=%\\\]\[\{\}])/sprintf("\\x%02x",ord($1))/eg}
"$k=$v"
} grep {defined($_[$#_]->{$_})
} keys %{$_[$#_]}) .'}'
: '[' .join(','
, map { my $k =$_;
$k =~s/([,=%\\\]\[\{\}])/sprintf("\\x%02x",ord($1))/eg;
$k
} grep {defined($_)
} @{$_[$#_]}) .']'
}
sub hrUnescape { # thaw($_[$#_])
$_[$#_] =~/^\{/ ? {hlUnescape(@_)} : $_[$#_] =~/^\[/ ? [hlUnescape(@_)] : $_[$#_]
}
sub hlUnescape { # %{thaw($_[$#_])}
if (ref($_[$#_])) {
my $k;
while ($k =each %{$_[$#_]}) {$_[$#_]->{$k} =undef};
$k =undef;
foreach (split / *[,=] */, ($_[$#_-1] =~/^[\{\[]/ ? substr($_[$#_-1], 1, -1) : $_[$#_-1])) {
/^\[\{\[]/
? hrUnescape($_[0], $_)
: s/\\x([0-9a-fA-F]{2})/chr hex($1)/eg;
if ($k) {$_[$#_]->{$k} =$_; $k =undef}
else {$k =$_}
}
$_[$#_];
}
else {
$_[$#_] =~/^[\{\[]/
? (map { /^\[\{\[]/
? hrUnescape($_[0], $_)
: s/\\x([0-9a-fA-F]{2})/chr hex($1)/eg;
} split / *[,=] */, substr($_[$#_], 1, -1))
: ($_[$#_])
}
}
sub keGet {
return($_[0]->{-pair}->[1]) if @_ <2;
my $v; $_[0]->{-handle}->get(krEscape($_[0], $_[1]), $v) ? undef : hrUnescape($v)
}
sub kePut {
my $r =0;
my $d =hrEscape($_[$#_]);
if (@_ >3) {
my $kn =krEscapeMv($_[0], $_[1]);
my $ko =krEscapeMv($_[0], $_[2]);
foreach my $k (@$kn) {
$_[0]->{-handle}->put($k, $d)
&& (&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: kePut('" .($_[0]->{-name}||'') ."','$k') -> '$!'"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef);
$r +=1;
}
foreach my $k (grep {my $v =$_; !grep {$v eq $_} @$kn} @$ko) {
$_[0]->{-handle}->del($k)
}
}
else {
foreach my $k (@{krEscapeMv($_[0], $_[1])}) {
$_[0]->{-handle}->put($k, $d)
&& (&{$_[0]->{-parent} ? $_[0]->{-parent}->{-die} : $DBIx::Web::LNG->{-die}}
("DBFile: kePut('" .($_[0]->{-name}||'') ."','$k') -> '$!'"
.($_[0]->{-parent} && $_[0]->{-parent}->{-ermd} ||'')
) ||undef);
$r +=1;
}
}
$r
}
sub keDel {
my $r =0;
foreach my $k (@{krEscapeMv($_[0], $_[1])}) {
$_[0]->{-handle}->del($k) ||($r +=1)
}
$r ||undef
}
sub keSeek {
my ($s, $flg, $sca, $subf, $subw) =@_;
# dir/cmp, keyArray, subFilter, subEval
my $p =$s->parent;
my $val =undef;
my $dbh =$s->{-handle};
my $dbs =0;
my @kds =map {!ref($_) ? $_ : $_->[0]} @{$s->{-table}->{-key}} # , '_rid'
if $s->{-table} && $s->{-table}->{-key};
my ($r, $k) =({}, []); # record hash & key array refs
my $ca =0;
my $subr=sub{undef};
foreach my $sck (@{$s->krEscapeMv($sca)}) {
my $key =$sck;
my $scl =length($sck);
if ($flg =~/^-*[af]eq/i) { # forward eq
$dbs =$dbh->seq($key, $val, R_CURSOR());
$subr=sub{do { return(undef) unless !$dbs && (defined($key) ? $sck eq substr($key, 0, $scl) : 0);
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_NEXT());
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[af]g[te]/i) { # forward g[te]
$key .="\x01" if $flg =~/gt$/i;
$dbs =$dbh->seq($key, $val, R_CURSOR());
$subr=sub{do { return(undef) unless !$dbs;
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_NEXT());
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[af]l[te]/i) { # forward l[te]
$dbs =$dbh->seq($key, $val, R_FIRST());
$subr=sub{do { return(undef) unless !$dbs
&& (!defined($key) ? 0
: $flg=~/lt$/i ? $sck lt substr($key, 0, $scl)
: $sck le substr($key, 0, $scl));
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_NEXT());
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[af]all/i) { # forward all
$dbs =$dbh->seq($key, $val, R_FIRST());
$subr=sub{do { return(undef) unless !$dbs;
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_NEXT());
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[bd]eq/i) { # backward eq
$key .="\x01";
$dbs =$dbh->seq($key, $val, R_CURSOR());
$dbs =$dbh->seq($key, $val, R_PREV());
$subr=sub{do { return(undef) unless !$dbs
&& (defined($key) ? $sck eq substr($key, 0, $scl) : 0);
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_PREV())
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[bd]l[te]/i) { # backward l[te]
$key .="\x01" if $flg =~/le$/i;
$dbs =$dbh->seq($key, $val, R_CURSOR());
$dbs =$dbh->seq($key, $val, R_PREV());
$subr=sub{do { return(undef) unless !$dbs;
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_PREV())
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[bd]g[te]/i) { # backward g[te]
$dbs =$dbh->seq($key, $val, R_LAST());
$subr=sub{do { return(undef) unless !$dbs
&& (!defined($key) ? 0
: $flg=~/gt$/i ? $sck gt substr($key, 0, $scl)
: $sck ge substr($key, 0, $scl));
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_PREV())
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
elsif ($flg =~/^-*[bd]all/i) { # backward all
$dbs =$dbh->seq($key, $val, R_LAST());
$subr=sub{do { return(undef) unless !$dbs;
$r =hlUnescape($s, $val, $r);
@$k=klUnescape($s, $key);
@$r{@kds}=@{$k} if @kds && !@$r{@kds};
$dbs =$dbh->seq($key, $val, R_PREV())
} while ($subf && !&$subf($s, $k, $r))
|| ($subw && ++$ca && &$subw($s, $k, $r));
$r }
}
}
$subr =DBIx::Web::dbmCursor->new($subr, -rec=>$r, -key=>$k);
if ($subw) {$subr->call; $subr =$ca};
$subr
}
sub keScan {
&{shift->parent->{-die}}("DBFile: 'keScan' not implemented yet!")
}
#########################################################
# Condition code block object, use isa($object,'CODE') !
#########################################################
package DBIx::Web::ccbHandle;
use strict;
sub new {
my ($c, $e) =@_;
if (!ref($e)) { # string to safe evaluate
my $c =$e;
my $m =eval('use Safe; Safe->new()');
eval{local $^W =0; $m->permit_only(qw(:default :base_core :browse))};
eval{local $^W =0; $m->share('@_', '$DBIx::Web::SELF')};
my $o =$DBIx::Web::SELF;
$e =sub{ local ($DBIx::Web::SELF, $^W) =($o, 0);
$m->reval($c)};
}
bless $e, $c;
$e
}
sub call { &{$_[0]}(@_[1..$#_]) }
sub fetch{ &{$_[0]}(@_[1..$#_]) }
sub eval { CORE::eval{&{$_[0]}(@_[1..$#_])} }
#########################################################
# DBM Cursor object
#########################################################
package DBIx::Web::dbmCursor;
use strict;
sub new {
my ($c, $e) =@_;
my $s={''=>$e, -rfl=>undef, @_[2..$#_]};
# -rec=>{}, -key=>[], -rfr=>[]; -query=>{}
bless $s, $c;
$s
}
sub setcols {
$_[0]->{NAME_db} =[map {!ref($_) ? $_ : ref($_) ne 'HASH' ? $_->[0] : (defined($_->{-expr}) ? $_->{-expr} : $_->{-fld})} ref($_[1]) ? @{$_[1]} : @_[1..$#_]];
$_[0]->{NAME} =[map {!ref($_) ? $_ : ref($_) ne 'HASH' ? $_->[1] : $_->{-fld}} ref($_[1]) ? @{$_[1]} : @_[1..$#_]];
$_[0]->{-rfr} =[map {$_[0]->{-rec}->{$_} =undef if !exists($_[0]->{-rec}->{$_});
\($_[0]->{-rec}->{$_})
} @{$_[0]->{NAME_db}}] if $_[0]->{-rec};
$_[0]->{-rfl} =[]; # record fields list
$_[0]
}
sub call {
&{$_[0]->{''}}(@_[1..$#_])
}
sub eval {
CORE::eval{&{$_[0]->{''}}(@_[1..$#_])}
}
sub fetch {
my $v =&{$_[0]->{''}}(@_[1..$#_]);
if ($v) {@{$_[0]->{-rfl}} =map {$$_} @{$_[0]->{-rfr}}; $_[0]->{-rfl}}
else {@{$_[0]->{-rfl}} =(); undef}
}
sub fetchrow_arrayref {
my $v =&{$_[0]->{''}}(@_[1..$#_]);
if ($v) {@{$_[0]->{-rfl}} =@${v}{@{$_[0]->{NAME_db}}}; $_[0]->{-rfl}}
else {@{$_[0]->{-rfl}} =(); undef}
}
sub fetchrow_hashref {
$_[0]->{-rec} =&{$_[0]->{''}}(@_[1..$#_]);
}
sub finish {
$_[0]->{''} =undef;
}
sub close {
$_[0]->{''} =undef;
}
#########################################################
# DBI Cursor object implementing filtering sub{}
#########################################################
package DBIx::Web::dbiCursor;
use strict;
use vars qw($AUTOLOAD);
sub new {
my ($c, $i) =@_;
my $s={''=>$i, @_[2..$#_]};
# -rec=>{}, -rfr=>[], -flt=>sub{}; -query=>{}
eval{$s->{'NAME'}=$s->{''}->{'NAME'}}
if ref($s->{''});
bless $s, $c;
$s
}
sub fetch {
return($_[0]->{''}->fetch(@_[1..$#_])) if !$_[0]->{-flt};
my ($r, $k);
while (1) {
while ($k = each %{$_[0]->{-rec}}) {$_[0]->{-rec}->{$k} =undef};
$r =$_[0]->{''}->fetch(@_[1..$#_]);
last if !$r || !$_[0]->{-flt}
|| &{$_[0]->{-flt}}($_[0],undef,$_[0]->{-rec})
}
$r
}
sub fetchrow_arrayref {
return($_[0]->{''}->fetchrow_arrayref(@_[1..$#_])) if !$_[0]->{-flt};
my ($r, $k);
while (1) {
while ($k = each %{$_[0]->{-rec}}) {$_[0]->{-rec}->{$k} =undef};
$r =$_[0]->{''}->fetchrow_arrayref(@_[1..$#_]);
last if !$r || !$_[0]->{-flt}
|| &{$_[0]->{-flt}}($_[0],undef,$_[0]->{-rec})
}
$r
}
sub fetchrow_hashref {
return($_[0]->{''}->fetchrow_hashref(@_[1..$#_])) if !$_[0]->{-flt};
my ($r, $k);
while (1) {
while ($k = each %{$_[0]->{-rec}}) {$_[0]->{-rec}->{$k} =undef};
$r =$_[0]->{''}->fetchrow_hashref(@_[1..$#_]);
last if !$r || !$_[0]->{-flt}
|| &{$_[0]->{-flt}}($_[0],undef,$_[0]->{-rec})
}
$r
}
sub finish {
$_[0]->{''}->finish(@_[1..$#_])
}
sub close {
eval {$_[0]->{''}->finish(@_[1..$#_])};
$_[0]->{''}=undef;
}
sub AUTOLOAD {
my $m =substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
confess("!object in AUTOLOAD of $AUTOLOAD") if !ref($_[0]);
$_[0]->{''}->$m(@_[1..$#_])
}
#########################################################
# UINION cursor/container operation cursor
#########################################################
package DBIx::Web::dbcUnion;
use strict;
sub new { # UNION peration cursor
my $c =shift; # (option=>value,...{hash data} || [array data] || cursor,...)
my $s={ -i =>[] # cursors or arrays, hashes are sorted to arrays
,-j =>[] # indexes of arrays
,-d =>[] # data buffers
,-asc =>1 # ascending order
,-lc =>1 # lowercase order compare
,-rl =>undef # right to left compare (for internal/external values)
,-all =>undef # non unique, records may be duplicated
,-rec =>{} # out record as hash
,-rfr =>[] # out record as array
,0 =>undef # inited mark
,'NAME' =>undef # column names, may be obtained from cursor or not used
};
while (defined($_[0])) {
if (!ref($_[0])) {
$s->{shift(@_)} =shift(@_)
}
else {
push @{$s->{-i}}, shift(@_)
}
}
if (!$s->{'NAME'}) {
foreach my $e (@{$s->{-i}}) {
next if !$e || (ref($e) =~/^(?:ARRAY|HASH)$/);
eval{$s->{'NAME'}=$e->{'NAME'} if ref($e->{'NAME'})};
last if $s->{'NAME'}
}
}
if (ref($s->{'NAME'})) {eval{
@{$s->{-rec}}[@{$s->{NAME}}] =();
@{$s->{-rfr}} =map {\($s->{-rec}->{$_})} @{$s->{NAME}};
}}
bless $s, $c;
$s
}
sub fetch {
my $s =$_[0];
return(undef) if !defined($s->{-i}) || !defined($s->{-rfr});
if (!$s->{0}) { # init processing
$s->{0} =1;
for (my $i =0; $i <=$#{$s->{-i}}; $i++) {
if (ref($s->{-i}->[$i]) eq 'HASH') {
use locale;
my $h =$s->{-i}->[$i];
$s->{-i}->[$i] =[
map {[$_, $h->$_]
} sort { $s->{-asc}
? lc($h->{$a}) cmp lc($h->{$b})
: lc($h->{$b}) cmp lc($h->{$a})
} keys %$h
];
$s->{-rl} =1 if !defined($s->{-rl});
}
if (ref($s->{-i}->[$i]) eq 'ARRAY') {
$s->{-d}->[$i] =[];
@{$s->{-d}->[$i]} =ref($s->{-i}->[$i]->[0])
? @{$s->{-i}->[$i]->[0]}
: $s->{-i}->[$i]->[0];
$s->{-j}->[$i] =0;
}
elsif ($s->{-i}->[$i]) {
if (!$s->{'NAME'}) {
eval{$s->{'NAME'}=$s->{-i}->[$i]->{'NAME'} if ref($s->{-i}->[$i]->{'NAME'})};
if (ref($s->{'NAME'})) {eval{
@{$s->{-rec}}[@{$s->{NAME}}] =();
@{$s->{-rfr}} =map {\($s->{-rec}->{$_})} @{$s->{NAME}};
}}
}
$s->{-d}->[$i] =$s->{-i}->[$i]->fetch(@_[1..$#_]);
}
else {
$s->{-d}->[$i] =undef;
}
}
}
my $m =undef;
for (my $i =0; $i <=$#{$s->{-i}}; $i++) {
if (!defined($s->{-d}->[$i])) {
next
}
elsif (!defined($m)) {
$m =$i;
next;
}
my ($vm, $vc) =($s->{-d}->[$m], $s->{-d}->[$i]);
my ($ce, $cc) =(1, 0);
my $j =$s->{-rl} ? $#{$vc} : 0;
{use locale;
while(1) {
$ce =0 if $ce
&& ( !defined($vm->[$j]) && !defined($vc->[$j])
? undef
: !defined($vm->[$j]) || !defined($vc->[$j])
? 1
: ($vm->[$j] ne $vc->[$j]));
$cc =1 if !$cc
&& ($s->{-asc}
? ( !defined($vc->[$j]) && !defined($vm->[$j])
? undef
: !defined($vc->[$j])
? 1
: !defined($vm->[$j])
? undef
: ($vc->[$j] =~/^\d+$/) && ($vm->[$j] =~/^\d+$/)
? $vc->[$j] < $vm->[$j]
: $s->{-lc}
? lc($vc->[$j]) lt lc($vm->[$j])
: $vc->[$j] lt $vm->[$j])
: ( !defined($vc->[$j]) && !defined($vm->[$j])
? undef
: !defined($vc->[$j])
? undef
: !defined($vm->[$j])
? 1
: ($vc->[$j] =~/^\d+$/) && ($vm->[$j] =~/^\d+$/)
? $vc->[$j] > $vm->[$j]
: $s->{-lc}
? lc($vc->[$j]) gt lc($vm->[$j])
: $vc->[$j] gt $vm->[$j])
);
last if $cc;
if ($s->{-rl}) { $j--; last if $j <0 }
else { $j++; last if $j >$#{$vc} }
}}
# print '[', join(';' , map {$_ ? join(',',@$_) : 'u'} @{$s->{-d}}), ']',
# $ce || 'ne', $cc ||'nc',"\n";
if ($cc) {
$m =$i
}
elsif ($ce && $s->{-all}) {
}
elsif ($ce) {
if (ref($s->{-i}->[$i]) ne 'ARRAY') {
$s->{-d}->[$i] =$s->{-i}->[$i]->fetch(@_[1..$#_])
}
elsif (++$s->{-j}->[$i] >$#{$s->{-i}->[$i]}) {
$s->{-d}->[$i] =undef;
$s->{-j}->[$i] =$#{$s->{-i}->[$i]} +1;
}
elsif (ref($s->{-i}->[$i]->[$s->{-j}->[$i]])) {
@{$s->{-d}->[$i]} =@{$s->{-i}->[$i]->[$s->{-j}->[$i]]}
}
else {
$s->{-d}->[$i]->[0] =$s->{-i}->[$i]->[$s->{-j}->[$i]]
}
}
}
if (!defined($m)) {
return($s->{-rfr} =undef)
}
else {
@{$s->{-rfr}} =@{$s->{-d}->[$m]};
# $s->{-rfr}->[0] =$m .' ' .$s->{-rfr}->[0];
# @{$s->{-rec}}[@{$s->{'NAME'}}] =@{$s->{-d}->[$m]}
# if $s->{'NAME'};
my $i =$m;
if (ref($s->{-i}->[$i]) ne 'ARRAY') {
$s->{-d}->[$i] =$s->{-i}->[$i]->fetch(@_[1..$#_])
}
elsif (++$s->{-j}->[$i] >$#{$s->{-i}->[$i]}) {
$s->{-d}->[$i] =undef;
$s->{-j}->[$i] =$#{$s->{-i}->[$i]} +1;
}
elsif (ref($s->{-i}->[$i]->[$s->{-j}->[$i]])) {
@{$s->{-d}->[$i]} =@{$s->{-i}->[$i]->[$s->{-j}->[$i]]}
}
else {
$s->{-d}->[$i]->[0] =$s->{-i}->[$i]->[$s->{-j}->[$i]]
}
return($s->{-rfr})
}
}
sub fetchrow_arrayref {
$_[0]->fetch(@_[1..$#_])
}
sub fetchrow_hashref {
$_[0]->fetch(@_[1..$#_])
&& $_[0]->{-rec}
}
sub finish {
my $s=$_[0];
return($s) if !$s->{-i};
foreach my $e (@{$s->{-i}}) {
eval{$e->finish()} if $e && (ref($e) !~/^(?:ARRAY|HASH)$/)
}
$s
}
sub close {
$_[0]->finish();
$_[0]->{-i} =undef;
$_[0]
}
sub DESTROY {
eval{$_[0]->close()}
}