--- loncom/LONCAPA.pm 2008/11/20 15:19:33 1.27 +++ loncom/LONCAPA.pm 2019/02/15 22:01:23 1.35.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network # Base routines # -# $Id: LONCAPA.pm,v 1.27 2008/11/20 15:19:33 jms Exp $ +# $Id: LONCAPA.pm,v 1.35.2.1 2019/02/15 22:01:23 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,13 +37,31 @@ use LONCAPA::Configuration; use Fcntl qw(:flock); use GDBM_File; use POSIX; +#use Apache::lonnet; my $loncapa_max_wait_time = 13; +#-------------------------------------------------------------------------- +# +# The constant definnitions below probably should really be in +# a configuration file somewhere (loncapa.conf?) and loaded so that they can be +# modified without requring source code changes: +# +# COURSE_CACHE_TIME - Number of minutes after which an unaccessed +# course.db or course_param.db file is considered +# to be a stale cache of this info. +# +# LONCAPA_TEMPDIR - Place loncapa puts temporary files +# + +my $COURSE_CACHE_TIME = 60; # minutes course cache file is considered valid. +my $LONCAPA_TEMPDIR = '/tmp/'; # relative to configuration{'lonTabDir'}. + use vars qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid + $match_community $match_name $match_lonid $match_handle $match_not_handle); @@ -52,35 +70,95 @@ require Exporter; our @ISA = qw (Exporter); our @EXPORT = qw(&add_get_param &escape &unescape &tie_domain_hash &untie_domain_hash &tie_user_hash - &untie_user_hash &propath); + &untie_user_hash &propath &tie_course); our @EXPORT_OK = qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid + $match_community $match_name $match_lonid - $match_handle $match_not_handle); + $match_handle $match_not_handle &tie_course); our %EXPORT_TAGS = ( 'match' =>[qw($match_domain $match_not_domain $match_username $match_not_username $match_courseid $match_not_courseid + $match_community $match_name $match_lonid $match_handle $match_not_handle)],); my %perlvar; -=pod +# +# If necessary fetch and tie a user's image of the course hash +# to the specified hash +# Parameters: +# domain - User's domain +# user - Name of user. +# course - Course number. +# cdom - Domain that is home to the course +# hash - reference to the has to tie. +# +# Side effects: +# a gdbm file and it's associated lock file will be created in the +# tmp directory tree. +# +# Returns: +# 0 - failure. +# 1 - success. +# +# Note: +# It's possible the required user's db file is already present in the tempdir. +# in that case a decision must be made about whether or not to just tie to it +# or to fetch it again. Remember this sub could be called in the context of a user +# other than the one whose data are being fetched. We don't know if that user already +# has a live session on this server. What we'll do is only re-fetch if the hash atime. +# is older than COURSE_CACHE_TIME...that is if it's been accessed relatively recently +# where COURSE_CACHE_TIME defines the caching time. +# +# The database files this function creates are of the form: +# $user@$domain_$course@$cdom.{db,lock} +# This differs from the prior filenames. Therefore if a module does its own +# caching (That's a coding no-no) and does not use this centralized sub, +# multiple cache files for the same course/user will be created. +# +sub tie_course { + my ($domain, $user, $course, $cdom, $hash) = @_; + + # + # See if we need to re-fetch the course data + # -=head2 NOTE: + +} -add_get_param() +# Return a string that is the path in which loncapa puts temp files: -Inputs are a url, and a hash ref of -form name => value pairs -takes care of properly adding the form name elements and values to the -the url doing proper escaping of the values and joining with ? or & as -needed +sub tempdir { + my $result = $perlvar{'lonDaemons'}.$LONCAPA_TEMPDIR; # to allow debugging. + return $result; +} + +# Return the default engine to use to render content of tags unless +# a domain, course, or user specific value exists. + +sub texengine { + return 'tth'; +} + +# Return the Linux distro where this LON-CAPA instance is running + +sub distro { + my $distro; + if (open(PIPE,"/home/httpd/perl/distprobe |")) { + $distro = ; + close(PIPE); + } + return $distro; +} -=cut +#---------------------------------------------------------------------- +# +# some of these subs need a bit of documentation sub add_get_param { my ($url,$form_data) = @_; @@ -114,8 +192,16 @@ sub unescape { return $str; } -$match_domain = $LONCAPA::domain_re = qr{[\w\-.]+}; -$match_not_domain = $LONCAPA::not_domain_re = qr{[^\w\-.]+}; +$LONCAPA::assess_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task)$}; +$LONCAPA::assess_page_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task|page)$}; +$LONCAPA::assess_page_seq_re = qr{\.(problem|exam|quiz|assess|survey|form|library|task|sequence|page)$}; +$LONCAPA::parse_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$}; +$LONCAPA::parse_page_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm|page)$}; +$LONCAPA::parse_page_sty_re = qr{\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm|page|sty)$}; + + +$match_domain = $LONCAPA::domain_re = qr{[[:alnum:]\-.]+}; +$match_not_domain = $LONCAPA::not_domain_re = qr{[^[:alnum:]\-.]+}; sub clean_domain { my ($domain) = @_; $domain =~ s/$match_not_domain//g; @@ -133,6 +219,7 @@ sub clean_username { $match_courseid = $LONCAPA::courseid_re = qr{\d[\w\-.]+}; +$match_community =$LONCAPA::community_re = qr{0[\w\-.]+}; $match_not_courseid = $LONCAPA::not_courseid_re = qr{[^\w\-.]+}; sub clean_courseid { my ($courseid) = @_; @@ -165,6 +252,47 @@ sub clean_handle { return $handle; } +# +# -- Ensure another process for same filesystem action is not running. +# lond uses for: apachereload; loncron uses for: lciptables +# + +sub try_to_lock { + my ($lockfile)=@_; + my $currentpid; + my $lastpid; + # Do not manipulate lock file as root + if ($>==0) { + return 0; + } + # Try to generate lock file. + # Wait 3 seconds. If same process id is in + # lock file, then assume lock file is stale, and + # go ahead. If process id's fluctuate, try + # for a maximum of 10 times. + for (0..10) { + if (-e $lockfile) { + open(LOCK,"<$lockfile"); + $currentpid=; + close LOCK; + if ($currentpid==$lastpid) { + last; + } + sleep 3; + $lastpid=$currentpid; + } else { + last; + } + if ($_==10) { + return 0; + } + } + open(LOCK,">$lockfile"); + print LOCK $$; + close LOCK; + return 1; +} + # -------------------------------------------- Return path to profile directory sub propath { @@ -175,8 +303,7 @@ sub propath { $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; my $proname="$perlvar{'lonUsersDir'}/$udom/$subdir/$uname"; return $proname; -} - +} sub tie_domain_hash { my ($domain,$namespace,$how,$loghead,$logtail) = @_; @@ -377,6 +504,7 @@ sub _do_hash_untie { } } + BEGIN { %perlvar=%{&LONCAPA::Configuration::read_conf('loncapa.conf')}; } @@ -385,6 +513,7 @@ BEGIN { __END__ +=pod =head1 NAME @@ -409,12 +538,14 @@ unpack non-word characters into CGI-comp pack CGI-compatible hex codes into actual non-word ASCII character =item add_get_param() + +Append escaped form elements (name=value etc.) to a url. Inputs: url (with or without exit GET from parameters), hash ref of form name => value pairs - Return: url with properly added the form name elements and values to the - the url doing proper escaping of the values and joining with ? or & + Return: url with form name elements and values appended to the + the url, doing proper escaping of the values and joining with ? or & as needed =item clean_handle() @@ -464,6 +595,37 @@ Returns: hash to which the database is tied. It's up to the caller to untie. undef if the has could not be tied. +=item tie_course + +Caches the course database into the temp directory in the context of a specific +user and ties it to a hash. +Parameters: + domain - Domain the user is in. + user - Username of the user. + course - Course specification + cdom - The course domain. + hash - Reference to the hash to tie. + +Returns: + 1 - Success + 0 - Failure. + +=item tie_course_params + +Caches the course parameter database into the temp directory in the context +of a specific user and ties it to a hash. +Parameters: + domain - Domain the user is in. + user - Username of the user. + course - course specification. + cdom - The course domain. + hash - reference to the hash to tie. + +Returns: + 1 - Success. + 0 - Failure./ + + =item locking_hash_tie() routines if you just have a filename return tied hashref or undef @@ -472,8 +634,17 @@ routines if you just have a filename ret =item db_filename_parts() +=back + +=item tempdir() + +Returns the file system path to the place loncapa temporary files should be placed/found. + + =head1 INTERNAL SUBROUTINES +=over + =item _do_hash_tie() =item _do_hash_untie()