[LON-CAPA-cvs] cvs: modules /gerd/loncapa_lernmodule README enrolldump.php /gerd/loncapa_lernmodule/loncapa studip.pm /gerd/loncapa_lernmodule/studip/public/assets/images/logos lon-capa.gif /gerd/loncapa_lernmodule/studip/templates/elearning loncapa_connected_link.php loncapa_connected_link_edit.php

www www at source.lon-capa.org
Thu Aug 30 04:38:47 EDT 2012


www		Thu Aug 30 08:38:47 2012 EDT

  Added files:                 
    /modules/gerd/loncapa_lernmodule	README enrolldump.php 
    /modules/gerd/loncapa_lernmodule/loncapa	studip.pm 
    /modules/gerd/loncapa_lernmodule/studip/public/assets/images/logos	
                                                                      	lon-capa.gif 
    /modules/gerd/loncapa_lernmodule/studip/templates/elearning	
                                                               	loncapa_connected_link.php 
                                                               	loncapa_connected_link_edit.php 
  Log:
  StudIP integration - work in progress. Files from Wibke Boerger
  
  
-------------- next part --------------

Index: modules/gerd/loncapa_lernmodule/enrolldump.php
+++ modules/gerd/loncapa_lernmodule/enrolldump.php
<?php
require '../lib/bootstrap.php';

if(!$_GET['course_id'] || !$_GET['inst_code']){
	exit();
}

$course_id = preg_replace('/\W/', '', $_GET['course_id']);
$inst_code = preg_replace('/\W/', '', $_GET['inst_code']);

$dbh = DBManager::get();

$stmt = "select username, vorname, nachname, email from object_contentmodules left join seminar_user on (object_id=seminar_id) left join auth_user_md5 using(user_id) where module_id=? and seminar_user.status='autor'";
$sth = $dbh->prepare($stmt);
$sth->execute(array($course_id));


$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE text>
<students>
";

while($row = $sth->fetch(PDO::FETCH_ASSOC)){
	$autharg = ''; 
	$authtype = 'internal';

	$xml .= "<student username=\"{$row['username']}\">
  <autharg>$autharg</autharg>
  <authtype>$authtype</authtype>
  <email>{$row['email']}</email>
  <enddate></enddate>
  <firstname>{$row['vorname']}</firstname>
  <generation></generation>
  <groupID></groupID>
  <lastname>{$row['nachname']}</lastname>
  <middlename></middlename>
  <startdate></startdate>
  <studentID></studentID>
 </student>\n";

}

$xml .= "</students>";

header('Content-disposition: attachment; filename='.$course_id.'_'.$inst_code.'_classlist.xml');
print $xml;
exit();
?>
Index: modules/gerd/loncapa_lernmodule/loncapa/studip.pm
+++ modules/gerd/loncapa_lernmodule/loncapa/studip.pm
# The LearningOnline Network
#
# Landing point for incoming StudIP requests 
#
# $Id: studip.pm,v 1.1 2012/08/30 08:38:46 www Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#

=pod

=head1 NAME

Apache::studip: incoming link from studip

=head1 SYNOPSIS

This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.
 
=head1 OVERVIEW

Incoming from StudIP

=cut

package Apache::studip;

use strict;

use Apache::Constants qw(:common :http);
use Apache::lonacc;
use Apache::lonnet;
use Apache::loncommon;
use Apache::lonlocal;
use LONCAPA;
use LWP::UserAgent;
use RPC::XML::ParserFactory;


# Config parameters

# url of studip webservice 
my $studip_url = 'http://192.168.122.3/studip/xmlrpc.php';

# password for studip webservice 
my $studip_pwd = 'qip(hF2tvYcU0ehd';

# list of remote ips which get access to course list
my @studip_ips = ('192.168.122.3', '192.168.122.1');

my $ua = LWP::UserAgent->new;
my $parser = RPC::XML::ParserFactory->new();

my $domain = &Apache::lonnet::default_login_domain();

# url patterns of valid routes 
my %routes = (
	'^courses$' => 'courses',
	'^course\/(?<course_id>[a-zA-Z0-9_]+)$' => 'course',
	'^enter\/(?<course_id>[a-zA-Z0-9_]+)$' => 'enter'
);

# registry of route callbacks
my %request_handlers;

# wrapper for lonnet's courseiddump
sub get_courseiddump{
	my ($domain, $courseid, $owner, $desc) = @_;

	my $domfilter = $domain;
	my $descfilter = $desc ? $desc : '.';
	my $sincefilter = 1;
	my $instcodefilter = '.';
	my $ownerfilter = $owner ? $owner : '.';
	my $coursefilter = $courseid ? $courseid : '.';
	my $hostidflag = undef;
	my $hostidref = undef;
	my $typefilter = 'Course';

	my  %courses = &Apache::lonnet::courseiddump($domfilter,$descfilter,$sincefilter,$instcodefilter,$ownerfilter,$coursefilter,$hostidflag,$hostidref,$typefilter);

	return %courses;
}

# get list of courses in this domain, optional parameters owner and search (description)
sub get_courses{
	my ($r, $params, $query_string) = @_;

	if(!allowed_ip($ENV{'REMOTE_ADDR'})){
		return &error_msg($r, FORBIDDEN);
	}

	if($query_string){
		&Apache::loncommon::get_unprocessed_cgi($query_string, ['owner', 'search']);
	}

	my %courses = &get_courseiddump($domain, undef, $env{'form.owner'}, $env{'form.search'});
	my $xml = &course_wrap(%courses);

	return &xml_response($r, $xml);
}
$request_handlers{'courses'} = \&get_courses;

# get one course, specified by course_id
sub get_course{
	my ($r, $params, $query_string) = @_;

	if(!&allowed_ip($ENV{'REMOTE_ADDR'})){
		return &error_msg($r, FORBIDDEN);
	}

	my ($dom, $id) = split(/_/, $$params{'course_id'}); 

	my %courses = &get_courseiddump($dom, $id);

	if(!%courses){
		return &error_msg($r,NOT_FOUND);
	}

	my $xml = &course_wrap(%courses);

	return &xml_response($r, $xml);
}
$request_handlers{'course'} = \&get_course;

# authenticate user and forward him to course contents
# only for users and courses in local domain
sub enter_course{
	my ($r, $params, $query_string) = @_;

	if($query_string){
		&Apache::loncommon::get_unprocessed_cgi($query_string, ['token']);
	}

	if(!$env{'form.token'}){
		return &error_msg($r, HTTP_UNAUTHORIZED);
	}

	# verify stuidp session
	my($error, $returned) = &make_studip_call('get_session_username', $env{'form.token'});

	if($error){
		&Apache::loncommon::content_type($r,'text/html');
		$r->send_http_header;
		$r->print($error);
		return OK;
	}

	my $user = $returned->value;

	if(!$user){
		&Apache::lonauth::failed($r, 'Couldn\'t verifiy token.', undef);
		return OK;
		#return &error_msg($r, HTTP_UNAUTHORIZED);
	}

	$user = &LONCAPA::clean_username($user);

	my %form = (
		'uname' => $user,
		'udom' => $domain
	);


	# only check against own domain
	my $uhome = &Apache::lonnet::homeserver($user, $domain);
	if($uhome eq 'no_host'){
		&Apache::lonauth::failed($r, "The user $user doesn\'t exist in this domain.", \%form);
		return OK;
		#return &error_msg($r, HTTP_UNAUTHORIZED);
	}


# user is authenticated from here on

	my ($cdom, $cid) = split(/_/, $$params{'course_id'});

	if($cdom eq $domain){
		my %roles = &Apache::lonnet::get_my_roles($user, $domain, 'userroles');
		my $matched_role = undef;
		for my $key (keys %roles){
			my($rcid, $rcdom, $role) = split(':', $key);
			if($rcid eq $cid && $rcdom eq $cdom){
				$matched_role = $role.'./'.$rcdom.'/'.$rcid;
				last;
			}
		}

		if($matched_role){
			$form{'role'} = $matched_role;
			$form{'symb'} = '/adm/navmaps';
		}
	}

	my $next_url = '/adm/roles';

	&Apache::lonauth::success($r, $user, $domain, $uhome, $next_url, undef, \%form);

	return OK;
}
$request_handlers{'enter'} = \&enter_course;

# wrap %courses hash into xml
sub course_wrap{
	my %courses = @_;
	my $xml = "<?xml version=\"1.0\"?>\n";
	$xml .= "<courses>\n";
	for my $id(keys %courses){
		$xml .= "<course>\n";
		$xml .= "<id>$id</id>\n";
		for my $p(keys %{$courses{$id}}){
			$xml .= "<$p>$courses{$id}{$p}</$p>\n";
		}
		$xml .= "</course>";
	}
	$xml .= "</courses>\n";
}

# XML response for requests for course lists
sub xml_response{
	my($r, $data) = @_;
	&Apache::loncommon::content_type($r,'application/xml');
	$r->send_http_header;
	$r->print($data);
	return OK;
}

sub html_wrap{
	my($title, $msg) = @_;

	return <<EOF;
<html>
<head><title>$title</title></head>
<body>
<h1>$title</h1>
<p>$msg</p>
</body>
</html>
EOF

}

sub error_msg{
	my($r, $status_code) = @_;

	&Apache::loncommon::content_type($r,'text/html');
	$r->send_http_header;
	return $status_code;
}

sub not_found{
	my $r = shift;
	&Apache::loncommon::content_type($r,'text/html');
	$r->send_http_header;
	$r->print(html_wrap('Not Found', 'The requested URL was not found on this server.'));
	return NOT_FOUND;
}

sub index_page{
	my $r = shift;

	&Apache::loncommon::content_type($r,'text/html');
	$r->send_http_header;
	$r->print(html_wrap('', '...this is not the page you\'re looking for.'));

	return OK;
}

# check if $ip is in the list of allowed server ips
sub allowed_ip{
	my $ip = shift;
	my $pattern = '^'.$ip.'$';
	my $c = grep(/$pattern/, @studip_ips);
	if($c == 1){
		return 1;
	}
	return 0;
}


# dispatching of routes
# valid routes (as defined above) are:
# /courses - to get a list of all courses in the domain
# /courses?owner=xy&search=title - to filter by owner and/or description
# /enter/{course_id}?token={token} - authenticate against token and enter the course with the id course_id 
#
sub handler{
	my $r = shift;

	my $path_info = $ENV{'PATH_INFO'};
	my $query_string = $ENV{'QUERY_STRING'};

	if(!$path_info || $path_info eq '/'){
		return &index_page($r);
	}

	$path_info =~ s/^\///;
	$path_info =~ s/\/$//;

	my $handler = undef;
	my %params = undef; 
	for my $pattern(keys %routes){
		my $endpoint = $routes{$pattern};
		if(($path_info =~ /$pattern/) && ($request_handlers{$endpoint})){
			$handler = $request_handlers{$endpoint};
			%params = %+;
			last;
		}
	}

	if($handler){
		return &$handler($r, \%params, $query_string);
	}

	return &error_msg($r, NOT_FOUND);

}


# XML-RPC request to studip
sub make_studip_call{
	my ($cmd, @args) = @_;

	my $xml = xmlrpc_wrap($cmd, $studip_pwd, @args);

	my $headers = HTTP::Headers->new() ;
	my $request = HTTP::Request->new('POST', $studip_url, $headers);
	$request->content($xml);

	$ua->timeout(4);
	my $response = $ua->request($request);

	my $returned;
	my $error = '';

	if($response->is_success()){
		my $rpcxml_response = $parser->parse($response->content);

		if(!$rpcxml_response->is_fault){
			$returned = $rpcxml_response->value;
		}
		else{
			$error = "ERROR: ".$rpcxml_response->value;
		}
	}
	else{
		$error = "ERROR: ".$response->status_line;
	}

	return ($error, $returned);
}

sub xmlrpc_wrap{
	my ($method, @params) = @_;

	my $paramstr = '';

	for(@params){
		$paramstr .= '<param><value><string>'.$_.'</string></value></param>'."\n";
	}

	return <<EOF;
<?xml version="1.0"?>
<methodCall>
<methodName>$method</methodName>
<params>
$paramstr
</params>
</methodCall>
EOF

}

1;

Index: modules/gerd/loncapa_lernmodule/studip/templates/elearning/loncapa_connected_link.php
+++ modules/gerd/loncapa_lernmodule/studip/templates/elearning/loncapa_connected_link.php
<a href="<?= htmlspecialchars($url) ?>" target="_blank">
    <?= makeButton('starten', 'img')?>
</a>

Index: modules/gerd/loncapa_lernmodule/studip/templates/elearning/loncapa_connected_link_edit.php
+++ modules/gerd/loncapa_lernmodule/studip/templates/elearning/loncapa_connected_link_edit.php
<form method="post" action="<?= URLHelper::getLink() ?>">
    <input type="hidden" name="view" value="<?= $view ?>">
    <input type="hidden" name="search_key" value="<?= $search_key ?>">
    <input type="hidden" name="cms_select" value="<?= $cms_select ?>">
    <input type="hidden" name="module_type" value="loncapa">
    <input type="hidden" name="module_id" value="<?= $current_module ?>">
    <input type="hidden" name="module_system_type" value="<?= $cms_type ?>">

    <? if ($connected) : ?>
        <?= makeButton('entfernen', 'input', false, 'remove') ?>
    <? else : ?>
        <?= makeButton('hinzufuegen', 'input', false, 'add') ?>
    <? endif ?>
</form>


More information about the LON-CAPA-cvs mailing list