no warnings; ################################################################################ sub peer_get { $_[1] -> {xls} = 0; my $item = peer_query (@_); $_REQUEST {__read_only} = $item -> {__read_only}; return $item; } ################################################################################ sub peer_execute { my $data = peer_query (@_); return $_REQUEST {error} if $_REQUEST {error}; redirect ({action => '', id => $data -> {id}}, {kind => 'js'}); return undef; } ################################################################################ sub peer_name { $preconf -> {peer_name} or die "Peer name not defined\n"; return $preconf -> {peer_name}; } ################################################################################ sub peer_reconnect { unless ($UA) { our $UA = LWP::UserAgent -> new ( agent => "Eludia/$Eludia_VERSION (" . peer_name () . ")", requests_redirectable => ['GET', 'HEAD', 'POST'], ); # $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1; } } ################################################################################ sub peer_proxy { my ($peer_server, $params) = @_; my $url = $preconf -> {peer_servers} -> {$peer_server} or die "Peer server '$peer_server' not defined\n"; $_REQUEST {__peer_server} = $peer_server; peer_reconnect (); $url .= '?sid='; $url .= $_REQUEST {sid}; my @keys = keys %$params; foreach my $k (@keys) { $url .= '&'; $url .= $k; $url .= '='; $url .= uri_escape ($params -> {$k}); } my $request = HTTP::Request -> new ('GET', $url); my $virgin = 1; my $response = $UA -> request ($request, sub { if ($virgin) { $r -> print ($r -> protocol); $r -> print (" 200OK\015\012"); $r -> print ($_[1] -> headers_as_string); $r -> print ("\015\012"); $virgin = 0; } $r -> print ($_[0]); }, ); $_REQUEST {__response_sent} = 1; } ################################################################################ sub peer_query { my ($peer_server, $params, $options) = @_; my $url = $preconf -> {peer_servers} -> {$peer_server} or die "Peer server '$peer_server' not defined\n"; peer_reconnect (); foreach my $k (keys %_REQUEST) { next if $k =~ /^__/ && $k ne '__edit'; next if exists $params -> {$k}; $params -> {$k} = ref $_REQUEST {$k} eq 'Math::FixedPrecision' ? $_REQUEST {$k} -> bstr () : $_REQUEST {$k}; } $params -> {__d} = 1; delete $params -> {select}; delete $params -> {xls}; my @headers = (Accept_Encoding => 'gzip'); $options -> {files} = [$options -> {file}] if $options -> {file}; if (ref $options -> {files} eq ARRAY) { foreach my $name (@{$options -> {files}}) { my $file = upload_file ({ name => $name, dir => 'upload/images'}); $params -> {'_' . $name} = [$file -> {real_path}, $params -> {'_' . $name}]; } push @headers, (Content_Type => 'form-data'); } my @args = ($url, @headers, Content => [ %$params ], ); my $request = POST (@args); my $response = $UA -> request ($request); foreach my $k (keys %$params) { my $v = $params -> {$k}; ref $v eq ARRAY or next; unlink $v -> [0]; } while (1) { $response -> is_success or die ("Invalid response from $peer_server: " . $response -> status_line . "\n"); my $dump = $response -> content; if ($response -> headers -> header ('Content-Encoding') eq 'gzip') { $dump = Compress::Zlib::memGunzip ($dump); } eval $dump; my ($root, $data) = (%$VAR1); undef $VAR1; $_REQUEST {__peer_server} = $peer_server; if ($root eq 'data') { return $data; } if ($root eq 'redirect') { $response = $UA -> request (GET $url . $data -> {url} . '&__d=1', Accept_Encoding => 'gzip', ); } elsif ($root eq 'error') { $_REQUEST {error} = $data -> {message}; $_REQUEST {error} = '#' . $data -> {field} . '#:' . $_REQUEST {error} if $data -> {field}; return $_REQUEST {error}; } else { die ("Invalid response from $peer_server: '$dump'\n"); } } } ############################################################################# sub fake_select { return { type => 'input_select', name => 'fake', values => [ {id => '0,-1', label => 'Все'}, {id => '-1', label => 'Удалённые'}, ], empty => 'Активные', } } ############################################################################# sub ids { my ($ar, $options) = @_; $options -> {field} ||= 'id'; $options -> {empty} ||= '-1'; $options -> {idx} ||= {}; my $ids = $options -> {empty}; my $idx = $options -> {idx}; foreach my $i (@$ar) { my $id = $i -> {$options -> {field}}; $id > 0 or next; $ids .= ','; $ids .= $id; if (ref $idx eq HASH) { $idx -> {$id} = $i; } elsif (ref $idx eq ARRAY) { $idx -> [$id] = $i; } } return wantarray ? ($ids, $idx) : $ids; } ############################################################################# sub is_off { my ($options, $value) = @_; return 0 unless $options -> {off}; if ($options -> {off} eq 'if zero') { return ($value == 0); } elsif ($options -> {off} eq 'if not') { return !$value; } else { return $options -> {off}; } } ################################################################################ sub async ($@) { my ($sub, @args) = @_; eval { &$sub (@args); }; print STDERR $@ if $@; # sql_disconnect (); # defined (my $child_pid = fork) or die "Cannot fork: $!\n"; # sql_reconnect (); # return $child_pid if $child_pid; # chdir '/' or die "Can't chdir to /: $!"; # close STDIN; # close STDOUT; # close STDERR; # eval { &$sub (@args); }; # sql_disconnect (); # CORE::exit (); } ################################################################################ sub send_mail { my ($options) = @_; warn "send_mail: " . Dumper ($options); my $to = $options -> {to}; ##### Multiple recipients if (ref $to eq ARRAY) { foreach (@$to) { $options -> {to} = $_; send_mail ($options); delete $options -> {href}; } return; } ##### To address if (!ref $to && $to > 0) { $to = sql_select_hash ("SELECT label, mail FROM $conf->{systables}->{users} WHERE id = ?", $to); } my $original_to; if ($preconf -> {mail} -> {to}) { $original_to = '' . Dumper ($to); $to = $preconf -> {mail} -> {to}; } my $real_to = $to; if (ref $to eq HASH) { $real_to = $to -> {mail}; $to = encode_mail_header ($to -> {label}, $options -> {header_charset}) . "<$real_to>"; } unless ($real_to =~ /\@/) { warn "send_mail: INVALID MAIL ADDRESS '$real_to'\n"; return; } ##### From address $options -> {from} ||= $preconf -> {mail} -> {from}; my $from = $options -> {from}; if (ref $from eq HASH) { $from -> {mail} ||= $from -> {address}; $from = encode_mail_header ($from -> {label}, $options -> {header_charset}) . "<" . $from -> {mail} . ">"; } ##### Message subject my $subject = encode_mail_header ($options -> {subject}, $options -> {header_charset}); ##### Message body $options -> {body_charset} ||= 'windows-1251'; $options -> {content_type} ||= 'text/plain'; if ($options -> {href}) { my $server_name = $preconf -> {mail} -> {server_name} || $ENV{HTTP_HOST}; $options -> {href} =~ /^http/ or $options -> {href} = "http://$server_name" . $options -> {href}; } if ($options -> {template}) { our $DATA = $options -> {data} if $options -> {data}; $DATA -> {href} = $options -> {href}; $options -> {text} = fill_in_template ($options -> {template}, '', {no_print => 1}); undef $DATA if $options -> {data}; } elsif ($options -> {href}) { $options -> {href} = "

$$options{href}" if $options -> {content_type} eq 'text/html'; $options -> {text} .= "\n\n" . $options -> {href}; } my $text = encode_base64 ($options -> {text} . "\n" . $original_to); unless ($^O eq 'MSWin32') { defined (my $child_pid = fork) or die "Cannot fork: $!\n"; return $child_pid if $child_pid; } ##### connecting... my $repeat = 10; my $smtp = undef; while ($repeat) { $repeat--; $smtp = Net::SMTP -> new ($preconf -> {mail} -> {host}, %{$preconf -> {mail} -> {options}}); $smtp or next; if ($preconf -> {mail} -> {user}) { $smtp -> auth ($preconf -> {mail} -> {user}, $preconf -> {mail} -> {password}) or die "SMTP AUTH error: " . $smtp -> code . ' ' . $smtp -> message; } last if $smtp; } unless (defined $smtp) { warn "Can't connect to $preconf->{mail}->{host}\n"; return; } # $smtp -> mail ($ENV{USER}); $smtp -> mail ($options -> {from} -> {address}); $smtp -> to ($real_to); $smtp -> data (); ##### sending main message $smtp -> datasend (< {attach} = [$options -> {attach}] if ($options -> {attach} && ref $options -> {attach} ne ARRAY); foreach my $attach (@{$options -> {attach}}) { if (-f $attach -> {real_path}) { my $type = $attach -> {type}; $type ||= 'application/octet-stream'; my $fn = $attach -> {file_name}; $fn ||= $attach -> {real_path}; $fn =~ s{.*[\\\/]}{}; $smtp -> datasend (< {real_path}) or die "Can't open $attach->{real_path}: $!"; while (read (FILE, $buf, 60*57)) { $smtp -> datasend (encode_base64 ($buf)); } close (FILE); } } $smtp -> datasend (< dataend (); $smtp -> quit; unless ($^O eq 'MSWin32') { CORE::exit (0); } } ################################################################################ sub encode_mail_header { my ($s, $charset) = @_; $charset ||= 'windows-1251'; if ($charset eq 'windows-1251') { $s =~ y{АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя}{бвчздеіцъйклмнопртуфхжигюыэящшьасБВЧЗДЕЈЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС}; $charset = 'koi8-r'; } $s = '=?' . $charset . '?B?' . encode_base64 ($s) . '?='; $s =~ s{[\n\r]}{}g; return $s; } ################################################################################ sub b64u_freeze { b64u_encode ( $Storable::VERSION ? Storable::freeze ($_[0]) : Dumper ($_[0]) ); } ################################################################################ sub b64u_thaw { my $serialized = b64u_decode ($_[0]); if ($Storable::VERSION) { return Storable::thaw ($serialized); } else { my $VAR1; eval $serialized; return $VAR1; } } ################################################################################ sub b64u_encode { my $s = MIME::Base64::encode ($_[0]); $s =~ y{+/=}{-_.}; $s =~ s{[\n\r]}{}gsm; return $s; } ################################################################################ sub b64u_decode { my $s = $_ [0]; $s =~ y{-_.}{+/=}; return MIME::Base64::decode ($s); } ################################################################################ sub require_fresh { my ($module_name, $fatal) = @_; check_systables (); my $file_name = $module_name; $file_name =~ s{(::)+}{\/}g; my $inc_key = $file_name . '.pm'; $file_name =~ s{^(.+?)\/}{\/}; my $found = 0; my $the_path = ''; foreach my $path (reverse (@$PACKAGE_ROOT)) { my $local_file_name = $path . $file_name . '.pm'; -f $local_file_name or next; $file_name = $local_file_name; $found = 1; $the_path = $path; $the_path =~ s{[\\\/]*(Content|Presentation)}{}; last; } my $is_config = $file_name =~ /Config\.pm$/ ? 1 : 0; $found or return "File not found: $file_name\n"; my $need_refresh = $preconf -> {core_spy_modules} || !$INC {$inc_key}; my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $last_modified, $ctime, $blksize, $blocks); if ($need_refresh && (!$is_config || !$CONFIG_IS_LOADED)) { ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $last_modified, $ctime, $blksize, $blocks) = stat ($file_name); my $last_load = $INC_FRESH {$module_name} + 0; $need_refresh = $last_load < $last_modified; } if ($need_refresh) { if ($_OLD_PACKAGE) { open (S, $file_name); my $src = join '', (); close (S); $src =~ s{package\s+$_OLD_PACKAGE}{package $_NEW_PACKAGE}g; $src =~ s{$_OLD_PACKAGE\:\:}{$_NEW_PACKAGE\:\:}g; eval $src; } else { do $file_name; } die $@ if $@; if ($is_config) { check_systables (); sql_assert_core_tables (); } if ( $is_config && $DB_MODEL && !exists $DB_MODEL -> {tables} ) { my %tables = (); tie %tables, Eludia::FileDumpHash, {path => $PACKAGE_ROOT -> [0] . '/Model'}; $DB_MODEL -> {tables} = \%tables; $DB_MODEL -> {splitted} = 1; } if ( $db && ( !$CONFIG_IS_LOADED || ( $last_modified > 0 + sql_select_scalar ( "SELECT unix_ts FROM $conf->{systables}->{__required_files} WHERE file_name = ?", $module_name ) ) ) ) { my $__last_update = sql_select_scalar ("SELECT unix_ts FROM $conf->{systables}->{__last_update}"); my $__time = int(time ()); if ($DB_MODEL && !$DB_MODEL -> {splitted}) { open (CONFIG, $file_name) || die "can't open $file_name: $!"; flock (CONFIG, LOCK_EX); eval { $model_update -> assert (%$DB_MODEL,core_voc_replacement_use => $conf -> {core_voc_replacement_use}); }; flock (CONFIG, LOCK_UN); close (CONFIG); die $@ if $@; } elsif (-d "$the_path/Model") { eval { opendir (DIR, "$the_path/Model") || die "can't opendir $the_path/Model: $!"; my @scripts = readdir (DIR); closedir DIR; foreach my $script (@scripts) { $script =~ /\.p[lm]$/ or next; my $name = $`; my $script_path = "$the_path/Model/$script"; ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $last_modified, $ctime, $blksize, $blocks) = stat ($script_path); if ($last_modified <= $__last_update) { next; } $__time = $last_modified if $__time < $last_modified; open (SCRIPT, $script_path) || die "can't lock $script_path: $!"; flock (SCRIPT, LOCK_EX); my ($__new_last_update, $pid) = sql_select_array ("SELECT unix_ts, pid FROM $conf->{systables}->{__last_update}"); if ($__new_last_update > $__last_update) { print STDERR "[$$] Oops, [$pid] bypassed us. Unlocking $name...\n"; flock (SCRIPT, LOCK_UN); close (SCRIPT); print STDERR "[$$] $name unlocked.\n"; $__last_update = -1; last; } print STDERR "[$$] Altering $name...\n"; my %db_model = %$DB_MODEL; $db_model {no_checksums} = 1; my $src = "\$db_model {tables} = {$name => {"; while (