Annotation of loncom/interface/londropadd.pm, revision 1.23
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to drop and add students in courses
3: #
1.23 ! albertel 4: # $Id: londropadd.pm,v 1.22 2002/04/04 17:32:45 albertel Exp $
1.17 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.1 www 28: # (Handler to set parameters for assessments
29: #
30: # (Handler to resolve ambiguous file locations
31: #
32: # (TeX Content Handler
33: #
1.14 harris41 34: # YEAR=2000
1.1 www 35: # 05/29/00,05/30,10/11 Gerd Kortemeyer)
36: #
37: # 10/11,10/12,10/16 Gerd Kortemeyer)
38: #
39: # 11/20,11/21,11/22,11/23,11/24,11/25,11/27,11/28,
40: # 12/08,12/12 Gerd Kortemeyer)
41: #
1.7 www 42: # 12/26,12/27,12/28,
1.14 harris41 43: # YEAR=2001
1.13 www 44: # 01/01/01,01/15,02/10,02/13,02/14,02/22 Gerd Kortemeyer
1.14 harris41 45: # 8/6 Scott Harrison
1.16 www 46: # Guy Albertelli
47: # 9/25 Gerd Kortemeyer
1.18 www 48: # 12/19 Guy Albertelli
49: # YEAR=2002
50: # 1/4 Gerd Kortemeyer
1.1 www 51:
52: package Apache::londropadd;
53:
54: use strict;
55: use Apache::lonnet;
56: use Apache::Constants qw(:common :http REDIRECT);
57:
1.10 www 58: # ================================================================ Print header
1.1 www 59:
1.10 www 60: sub header {
61: my $r=shift;
62: $r->print(<<ENDHEAD);
1.1 www 63: <html>
64: <head>
65: <title>LON-CAPA Student Drop/Add</title>
66: </head>
67: <body bgcolor="#FFFFFF">
68: <img align=right src=/adm/lonIcons/lonlogos.gif>
69: <h1>Drop/Add Students</h1>
70: <form method="post" enctype="multipart/form-data"
71: action="/adm/dropadd" name="studentform">
72: <h2>Course: $ENV{'course.'.$ENV{'request.course.id'}.'.description'}</h2>
73: ENDHEAD
1.10 www 74: }
75:
76: # ========================================================= Store uploaded file
77: # needs $ENV{'form.upfile'}
78: # return $datatoken to be put into hidden field
79:
80: sub upfile_store {
81: my $r=shift;
82: $ENV{'form.upfile'}=~s/\r/\n/gs;
83: $ENV{'form.upfile'}=~s/\f/\n/gs;
84: $ENV{'form.upfile'}=~s/\n+/\n/gs;
85: $ENV{'form.upfile'}=~s/\n+$//gs;
86:
87: my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}.
88: '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$;
89: {
90: my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons').
91: '/tmp/'.$datatoken.'.tmp');
92: print $fh $ENV{'form.upfile'};
93: }
94: return $datatoken;
95: }
96:
97: # ================================================= Load uploaded file from tmp
98: # needs $ENV{'form.datatoken'}
99: # sets $ENV{'form.upfile'}
100:
101: sub load_tmp_file {
102: my $r=shift;
103: my @studentdata=();
104: {
105: my $fh;
106: if ($fh=Apache::File->new($r->dir_config('lonDaemons').
107: '/tmp/'.$ENV{'form.datatoken'}.'.tmp')) {
108: @studentdata=<$fh>;
109: }
110: }
111: $ENV{'form.upfile'}=join('',@studentdata);
112: }
113:
114: # ========================================= Separate uploaded file into records
115: # returns array of records
116:
117: sub upfile_record_sep {
118: if ($ENV{'form.upfiletype'} eq 'xml') {
119: } else {
120: return split(/\n/,$ENV{'form.upfile'});
121: }
122: }
123:
124: # =============================================== Separate a record into fields
125:
126: sub record_sep {
127: my $record=shift;
128: my %components=();
129: if ($ENV{'form.upfiletype'} eq 'xml') {
130: } elsif ($ENV{'form.upfiletype'} eq 'space') {
131: my $i=0;
1.21 matthew 132: foreach (split(/\s+/,$record)) {
1.10 www 133: my $field=$_;
134: $field=~s/^(\"|\')//;
135: $field=~s/(\"|\')$//;
136: $components{$i}=$field;
137: $i++;
1.20 harris41 138: }
1.10 www 139: } elsif ($ENV{'form.upfiletype'} eq 'tab') {
140: my $i=0;
1.20 harris41 141: foreach (split(/\t+/,$record)) {
1.10 www 142: my $field=$_;
143: $field=~s/^(\"|\')//;
144: $field=~s/(\"|\')$//;
145: $components{$i}=$field;
146: $i++;
1.20 harris41 147: }
1.10 www 148: } else {
149: my @allfields=split(/\,/,$record);
150: my $i=0;
151: my $j;
152: for ($j=0;$j<=$#allfields;$j++) {
153: my $field=$allfields[$j];
154: if ($field=~/^\s*(\"|\')/) {
155: my $delimiter=$1;
156: while (($field!~/$delimiter$/) && ($j<$#allfields)) {
157: $j++;
158: $field.=','.$allfields[$j];
159: }
160: $field=~s/^\s*$delimiter//;
161: $field=~s/$delimiter\s*$//;
162: }
163: $components{$i}=$field;
164: $i++;
165: }
166: }
167: return %components;
168: }
169:
170: # =========== Drop student from all sections of a course, except optional $csec
171:
172: sub dropstudent {
173: my ($udom,$unam,$courseid,$csec)=@_;
174: $courseid=~s/\_/\//g;
175: $courseid=~s/^(\w)/\/$1/;
1.20 harris41 176: foreach (split(/\&/,
177: &Apache::lonnet::reply('dump:'.$udom.':'.$unam.':roles',
178: &Apache::lonnet::homeserver($unam,$udom)))) {
1.10 www 179: my ($key,$value)=split(/\=/,$_);
180: $key=&Apache::lonnet::unescape($key);
181: if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) {
182: my $section=$1;
183: if ($key eq $courseid.'_st') { $section=''; }
1.16 www 184: if (((!$section) && (!$csec)) || ($section ne $csec)) {
1.10 www 185: my ($dummy,$end,$start)=split(/\_/,
186: &Apache::lonnet::unescape($value));
187: my $now=time;
188: my $notactive=0;
189: if ($start) {
190: if ($now<$start) { $notactive=1; }
191: }
192: if ($end) {
193: if ($now>$end) { $notactive=1; }
194: }
195: unless ($notactive) {
196: my $reply=&Apache::lonnet::modifystudent(
197: $udom,$unam,'','','',
198: '','','','',$section,time);
199: }
200: }
201: }
1.20 harris41 202: }
1.10 www 203: }
204:
205: # ============================================================== Menu Phase One
206:
207: sub menu_phase_one {
208: my $r=shift;
209: $r->print(<<ENDUPFORM);
1.2 www 210: <input type=hidden name=phase value=two>
211: <hr>
212: <h3>Upload a courselist</h3>
213: <input type=file name=upfile size=50>
214: <br>Type: <select name=upfiletype>
215: <option value=csv>CSV (comma separated values, spreadsheet)</option>
216: <option value=space>Space separated</option>
217: <option value=tab>Tabulator separated</option>
218: <option value=xml>HTML/XML</option>
219: </select>
220: <p><input type=submit name=fileupload value="Upload Courselist">
221: <hr>
222: <h3>Enroll a single student</h3>
223: <p><input type=submit name=enroll value="Enroll Student">
224: <hr>
1.11 www 225: <h3>Drop students</h3>
226: <p><input type=submit name=drop value="Selection List">
1.2 www 227: ENDUPFORM
1.10 www 228: }
229:
230:
1.23 ! albertel 231: sub phase_two_header {
! 232: my ($r,$datatoken,$distotal,$krbdefdom)=@_;
1.10 www 233: $r->print(<<ENDPICK);
1.2 www 234: <input type=hidden name=phase value=three>
235: <input type=hidden name=datatoken value="$datatoken">
236: <input type=hidden name=upfiletype value=$ENV{'form.upfiletype'}>
237: <hr>
238: <h3>Identify fields</h3>
1.22 albertel 239: Total number of records found in file: $distotal <hr />
240: Enter as many fields as you can. The system will inform you and bring you back
241: to this page if the data selected is insufficient to run your class.<hr />
1.3 www 242: <script>
243: function verify(vf) {
244: var founduname=0;
245: var foundpwd=0;
246: var foundname=0;
247: var foundid=0;
248: var foundsec=0;
249: var foundatype=0;
250: var tw;
251: var message='';
252: for (i=0;i<=vf.nfields.value;i++) {
253: tw=eval('vf.f'+i+'.selectedIndex');
254: if (tw==1) { founduname=1; }
255: if ((tw>=2) && (tw<=6)) { foundname=1; }
256: if (tw==7) { foundid=1; }
257: if (tw==8) { foundsec=1; }
258: if (tw==9) { foundpwd=1; }
259: }
260: if (founduname==0) {
261: alert('You need to specify at least the username field');
262: return;
263: }
264: if (vf.login[0].checked) {
265: foundatype=1;
266: if (vf.krbdom.value=='') {
267: alert('You need to specify the Kerberos domain');
268: return;
269: }
270: }
271: if (vf.login[1].checked) {
272: foundatype=1;
273: if ((vf.intpwd.value=='') && (foundpwd==0)) {
274: alert('You need to specify the initial password');
275: return;
276: }
277: }
1.15 albertel 278: if (vf.login[2].checked) {
279: foundatype=1;
280: //An argument is not required
281: }
1.3 www 282: if (foundatype==0) {
283: alert('You need to set the login type');
284: return;
285: }
286: if (foundname==0) { message='No name fields specified. '; }
287: if (foundid==0) { message+='No ID or student number field specified. '; }
288: if (foundsec==0) { message+='No section or group field specified. '; }
1.4 www 289: if (vf.startdate.value=='') {
290: message+='No starting date set. ';
1.3 www 291: }
1.4 www 292: if (vf.enddate.value=='') {
293: message+='No ending date set. ';
294: }
295: if ((vf.enddate.value!='') && (vf.startdate.value!='')) {
1.10 www 296: if (Math.round(vf.enddate.value)<Math.round(vf.startdate.value)) {
1.4 www 297: alert('Ending date is before starting date');
298: return;
299: }
300: }
301: if (message!='') {
302: message+='Continue enrollment?';
303: if (confirm(message)) {
304: pclose();
305: vf.submit();
306: }
307: } else {
308: pclose();
309: vf.submit();
310: }
1.3 www 311: }
312:
313: function flip(vf,tf) {
314: var nw=eval('vf.f'+tf+'.selectedIndex');
315: var i;
316: for (i=0;i<=vf.nfields.value;i++) {
317: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
318: eval('vf.f'+i+'.selectedIndex=0;')
319: }
320: }
321: if (nw==2) {
322: for (i=0;i<=vf.nfields.value;i++) {
323: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
324: (eval('vf.f'+i+'.selectedIndex')<=6)) {
325: eval('vf.f'+i+'.selectedIndex=0;')
326: }
327: }
328: }
329: if ((nw>=3) && (nw<=6)) {
330: for (i=0;i<=vf.nfields.value;i++) {
331: if (eval('vf.f'+i+'.selectedIndex')==2) {
332: eval('vf.f'+i+'.selectedIndex=0;')
333: }
334: }
335: }
336: if (nw==9) {
337: vf.login[1].checked=true;
338: vf.intpwd.value='';
339: vf.krbdom.value='';
1.15 albertel 340: vf.locarg.value='';
1.3 www 341: }
342:
343: }
344:
345: function clearpwd(vf) {
346: var i;
347: for (i=0;i<=vf.nfields.value;i++) {
348: if (eval('vf.f'+i+'.selectedIndex')==9) {
349: eval('vf.f'+i+'.selectedIndex=0;')
350: }
351: }
352: }
353:
354: function setkrb(vf) {
355: if (vf.krbdom.value!='') {
356: clearpwd(vf);
357: vf.login[0].checked=true;
358: vf.krbdom.value=vf.krbdom.value.toUpperCase();
359: vf.intpwd.value='';
360: }
361: }
362:
363: function setint(vf) {
364: if (vf.intpwd.value!='') {
365: clearpwd(vf);
366: vf.login[1].checked=true;
367: vf.krbdom.value='';
368: }
369: }
370:
371: function clickkrb(vf) {
372: vf.krbdom.value='$krbdefdom';
373: clearpwd(vf);
374: vf.intpwd.value='';
375: }
376:
377: function clickint(vf) {
378: vf.krbdom.value='';
379: }
380:
1.4 www 381: function pclose() {
382: parmwin=window.open("/adm/rat/empty.html","LONCAPAparms",
383: "height=350,width=350,scrollbars=no,menubar=no");
384: parmwin.close();
385: }
386:
387: function pjump(type,dis,value,marker,ret,call) {
388: parmwin=window.open("/adm/rat/parameter.html?type="+escape(type)
389: +"&value="+escape(value)+"&marker="+escape(marker)
390: +"&return="+escape(ret)
391: +"&call="+escape(call)+"&name="+escape(dis),"LONCAPAparms",
392: "height=350,width=350,scrollbars=no,menubar=no");
393:
394: }
395:
396: function dateset() {
397: if (document.studentform.pres_marker.value=='end') {
398: document.studentform.enddate.value=
399: document.studentform.pres_value.value;
400: }
401: if (document.studentform.pres_marker.value=='start') {
402: document.studentform.startdate.value=
403: document.studentform.pres_value.value;
404: }
405: pclose();
406: }
1.3 www 407:
408: </script>
1.2 www 409: <table border=2><tr><th>Field</th><th>Samples</th></tr>
410: ENDPICK
1.23 ! albertel 411: }
1.10 www 412:
1.23 ! albertel 413: sub phase_two_end {
! 414: my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_;
! 415: $r->print(<<ENDPICK);
1.3 www 416: </table>
1.10 www 417: <input type=hidden name=nfields value=$i>
418: <input type=hidden name=keyfields value="$keyfields">
1.3 www 419: <h3>Login Type</h3>
1.15 albertel 420: <p>Note: this will not take effect if the user already exists</p>
421: <p>
422: <input type=radio name=login value=krb onClick="clickkrb(this.form);" />
1.3 www 423: Kerberos authenticated with domain
1.15 albertel 424: <input type=text size=10 name=krbdom onChange="setkrb(this.form);" />
425: </p>
426: <p>
427: <input type=radio name=login value=int onClick="clickint(this.form);" />
1.3 www 428: Internally authenticated (with initial password
1.15 albertel 429: <input type=text size=10 name=intpwd onChange="setint(this.form);" />)
430: </p>
431: <p>
432: <input type=radio name=login value=loc onClick="clickloc(this.form);" />
433: Local Authentication with argument
434: <input type=text size=10 name=locarg onChange="setloc(this.form);" />
435: </p>
1.5 www 436: <h3>LON-CAPA Domain for Students</h3>
1.4 www 437: LON-CAPA domain: <input type=text size=10 value=$defdom name=lcdomain><p>
1.5 www 438: <h3>Starting and Ending Dates</h3>
1.4 www 439: <input type="hidden" value='' name="pres_value">
440: <input type="hidden" value='' name="pres_type">
441: <input type="hidden" value='' name="pres_marker">
442: <input type="hidden" value='$today' name=startdate>
443: <input type="hidden" value='$halfyear' name=enddate>
444: <a
445: href="javascript:pjump('date_start','Enrollment Starting Date',document.studentform.startdate.value,'start','studentform.pres','dateset');"
446: >Set Starting Date</a><p>
447:
448: <a
449: href="javascript:pjump('date_end','Enrollment Ending Date',document.studentform.enddate.value,'end','studentform.pres','dateset');"
450: >Set Ending Date</a><p>
1.5 www 451: <h3>Full Update</h3>
452: <input type=checkbox name=fullup value=yes> Full update
1.11 www 453: (also print list of users not enrolled anymore)<p>
1.18 www 454: <h3>ID/Student Number</h3>
455: <input type=checkbox name=forceid value=yes>
456: Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
1.19 www 457: (only do if you know what you are doing)<p>
1.6 www 458: <input type=button onClick="verify(this.form)" value="Update Courselist"><br>
459: Note: for large courses, this operation might be time consuming.
1.3 www 460: ENDPICK
1.23 ! albertel 461: }
! 462: # ======================================================= Menu Phase Two Upload
! 463:
! 464: sub menu_phase_two_upload {
! 465: my $r=shift;
! 466:
! 467: my $datatoken=&upfile_store($r);
! 468:
! 469: my @records=&upfile_record_sep();
! 470: my $total=$#records;
! 471: my $distotal=$total+1;
! 472:
! 473: $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
! 474: my $krbdefdom=$1;
! 475: $krbdefdom=~tr/a-z/A-Z/;
! 476:
! 477: my $today=time;
! 478: my $halfyear=$today+15552000;
! 479:
! 480: my $defdom=$r->dir_config('lonDefDomain');
! 481:
! 482: &phase_two_header($r,$datatoken,$distotal,$krbdefdom);
! 483:
! 484: my %sone; my %stwo; my %sthree;
! 485: my $i=0;
! 486:
! 487: if ($total>=0) {
! 488: %sone=&record_sep($records[0]);
! 489: if ($total>=1) {
! 490: %stwo=&record_sep($records[1]);
! 491: }
! 492: if ($total>=2) {
! 493: %sthree=&record_sep($records[2]);
! 494: }
! 495: foreach (sort keys %sone) {
! 496: $r->print('<tr><td><select name=f'.$i.
! 497: ' onChange="flip(this.form,'.$i.');">');
! 498: foreach ('none: ','username:Username',
! 499: 'names:Last Name, First Names',
! 500: 'fname:First Name','mname:Middle Names/Initials',
! 501: 'lname:Last Name','gen:Generation',
! 502: 'id:ID/Student Number','sec:Group/Section',
! 503: 'ipwd:Initial Password') {
! 504: my ($value,$display)=split(/\:/,$_);
! 505: $r->print('<option value='.$value.'>'.$display.
! 506: '</option>');
! 507: }
! 508: $r->print('</select></td><td>');
! 509: if (defined($sone{$_})) {
! 510: $r->print($sone{$_}."</br>\n");
! 511: }
! 512: if (defined($stwo{$_})) {
! 513: $r->print($stwo{$_}."</br>\n");
! 514: }
! 515: if (defined($sthree{$_})) {
! 516: $r->print($sthree{$_}."</br>\n");
! 517: }
! 518: $r->print('</td></tr>');
! 519: $i++;
! 520: }
! 521: $i--;
! 522: }
! 523: my $keyfields=join(',',sort keys %sone);
! 524:
! 525: &phase_two_end($r,$i,$keyfields,$defdom,$today,$halfyear);
1.10 www 526: }
527:
1.12 www 528: # ======================================================= Enroll single student
529:
530: sub enroll_single_student {
531: my $r=shift;
532: $r->print('<h3>Enrolling Student</h3>');
533: if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\W/)&&
534: ($ENV{'form.cdomain'})&&($ENV{'form.cdomain'}!~/\W/)) {
535: my $amode='';
536: my $genpwd='';
537: if ($ENV{'form.login'} eq 'krb') {
538: $amode='krb4';
539: $genpwd=$ENV{'form.krbdom'};
540: } elsif ($ENV{'form.login'} eq 'int') {
541: $amode='internal';
542: $genpwd=$ENV{'form.intpwd'};
1.15 albertel 543: } elsif ($ENV{'form.login'} eq 'loc') {
544: $amode='localauth';
545: $genpwd=$ENV{'form.locarg'};
546: if (!$genpwd) { $genpwd=" "; }
547: }
1.12 www 548: if (($amode) && ($genpwd)) {
549: &dropstudent($ENV{'form.cdomain'},$ENV{'form.cuname'},
550: $ENV{'request.course.id'},$ENV{'form.csec'});
551: $r->print(&Apache::lonnet::modifystudent(
552: $ENV{'form.cdomain'},$ENV{'form.cuname'},
553: $ENV{'form.cstid'},$amode,$genpwd,
554: $ENV{'form.cfirst'},$ENV{'form.cmiddle'},
555: $ENV{'form.clast'},$ENV{'form.cgen'},
556: $ENV{'form.csec'},$ENV{'form.enddate'},
1.19 www 557: $ENV{'form.startdate'},$ENV{'form.forceid'}));
1.12 www 558: } else {
559: $r->print('Invalid login mode or password');
560: }
561: } else {
562: $r->print('Invalid username or domain');
563: }
564: }
565:
1.10 www 566: # ======================================================= Menu Phase Two Enroll
567:
568: sub menu_phase_two_enroll {
569: my $r=shift;
1.11 www 570:
571: $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
572: my $krbdefdom=$1;
573: $krbdefdom=~tr/a-z/A-Z/;
574:
575: my $today=time;
576: my $halfyear=$today+15552000;
577:
578: my $defdom=$r->dir_config('lonDefDomain');
579:
580: $r->print(<<ENDSENROLL);
1.12 www 581: <script>
582: function verify(vf) {
583: var founduname=0;
584: var foundpwd=0;
585: var foundname=0;
586: var foundid=0;
587: var foundsec=0;
588: var foundatype=0;
589: var tw;
590: var message='';
1.14 harris41 591: if ((typeof(vf.cuname.value)!="undefined") && (vf.cuname.value!='') &&
592: (typeof(vf.cdomain.value)!="undefined") && (vf.cdomain.value!='')) {
1.12 www 593: founduname=1;
594: }
1.14 harris41 595: if ((typeof(vf.cfirst.value)!="undefined") && (vf.cfirst.value!='') &&
596: (typeof(vf.clast.value)!="undefined") && (vf.clast.value!='')) {
1.12 www 597: foundname=1;
598: }
1.14 harris41 599: if ((typeof(vf.csec.value)!="undefined") && (vf.csec.value!='')) {
1.12 www 600: foundsec=1;
601: }
1.14 harris41 602: if ((typeof(vf.cstid.value)!="undefined") && (vf.cstid.value!='')) {
1.12 www 603: foundid=1;
604: }
605: if (founduname==0) {
606: alert('You need to specify at least the username and domain fields');
607: return;
608: }
609: if (vf.login[0].checked) {
610: foundatype=1;
611: if (vf.krbdom.value=='') {
612: alert('You need to specify the Kerberos domain');
613: return;
614: }
615: }
616: if (vf.login[1].checked) {
617: foundatype=1;
618: if ((vf.intpwd.value=='') && (foundpwd==0)) {
619: alert('You need to specify the initial password');
620: return;
621: }
622: }
1.15 albertel 623: if (vf.login[2].checked) {
624: foundatype=1;
625: //An argument is not required
626: }
1.12 www 627: if (foundatype==0) {
628: alert('You need to set the login type');
629: return;
630: }
631: if (foundname==0) { message='No first and last name specified. '; }
632: if (foundid==0) { message+='No ID or student number field specified. '; }
633: if (foundsec==0) { message+='No section or group field specified. '; }
634: if (vf.startdate.value=='') {
635: message+='No starting date set. ';
636: }
637: if (vf.enddate.value=='') {
638: message+='No ending date set. ';
639: }
640: if ((vf.enddate.value!='') && (vf.startdate.value!='')) {
641: if (Math.round(vf.enddate.value)<Math.round(vf.startdate.value)) {
642: alert('Ending date is before starting date');
643: return;
644: }
645: }
646: if (message!='') {
647: message+='Continue enrollment?';
648: if (confirm(message)) {
649: pclose();
650: vf.submit();
651: }
652: } else {
653: pclose();
654: vf.submit();
655: }
656: }
657:
658: function setkrb(vf) {
659: if (vf.krbdom.value!='') {
660: vf.login[0].checked=true;
661: vf.krbdom.value=vf.krbdom.value.toUpperCase();
662: vf.intpwd.value='';
1.15 albertel 663: vf.locarg.value='';
1.12 www 664: }
665: }
666:
667: function setint(vf) {
668: if (vf.intpwd.value!='') {
669: vf.login[1].checked=true;
670: vf.krbdom.value='';
1.15 albertel 671: vf.locarg.value='';
672: }
673: }
674:
675: function setloc(vf) {
676: if (vf.locarg.value!='') {
677: vf.login[2].checked=true;
678: vf.krbdom.value='';
679: vf.intpwd.value='';
1.12 www 680: }
681: }
682:
683: function clickkrb(vf) {
684: vf.krbdom.value='$krbdefdom';
685: vf.intpwd.value='';
1.15 albertel 686: vf.locarg.value='';
1.12 www 687: }
688:
689: function clickint(vf) {
690: vf.krbdom.value='';
1.15 albertel 691: vf.locarg.value='';
692: }
693:
694: function clickloc(vf) {
695: vf.krbdom.value='';
696: vf.intpwd.value='';
1.12 www 697: }
698:
699: function pclose() {
700: parmwin=window.open("/adm/rat/empty.html","LONCAPAparms",
701: "height=350,width=350,scrollbars=no,menubar=no");
702: parmwin.close();
703: }
704:
705: function pjump(type,dis,value,marker,ret,call) {
706: parmwin=window.open("/adm/rat/parameter.html?type="+escape(type)
707: +"&value="+escape(value)+"&marker="+escape(marker)
708: +"&return="+escape(ret)
709: +"&call="+escape(call)+"&name="+escape(dis),"LONCAPAparms",
710: "height=350,width=350,scrollbars=no,menubar=no");
711:
712: }
713:
714: function dateset() {
715: if (document.studentform.pres_marker.value=='end') {
716: document.studentform.enddate.value=
717: document.studentform.pres_value.value;
718: }
719: if (document.studentform.pres_marker.value=='start') {
720: document.studentform.startdate.value=
721: document.studentform.pres_value.value;
722: }
723: pclose();
724: }
725:
726: </script>
1.11 www 727: <h3>Personal Data</h3>
728: First Name: <input type=text name=cfirst size=15><br>
729: Middle Name: <input type=text name=cmiddle size=15><br>
730: Last Name: <input type=text name=clast size=15><br>
731: Generation: <input type=text name=cgen size=5><p>
732:
733: ID/Student Number: <input type=text name=cstid size=10><p>
734:
735: Group/Section: <input type=text name=csec size=5><p>
736:
1.12 www 737: <h3>Login Data</h3>
738: Username: <input type=text name=cuname size=15><p>
739: Domain: <input type=text size=10 value=$defdom name=cdomain><p>
740: Note: login settings below will not take effect if the user already exists<p>
1.11 www 741:
742: <input type=radio name=login value=krb onClick="clickkrb(this.form);">
743: Kerberos authenticated with domain
744: <input type=text size=10 name=krbdom onChange="setkrb(this.form);"><p>
745: <input type=radio name=login value=int onClick="clickint(this.form);">
746: Internally authenticated (with initial password
747: <input type=text size=10 name=intpwd onChange="setint(this.form);">)
1.15 albertel 748: <p>
749: <input type=radio name=login value=loc onClick="clickloc(this.form);" />
750: Local Authentication with argument
751: <input type=text size=10 name=locarg onChange="setloc(this.form);" />
752: </p>
1.11 www 753: <h3>Starting and Ending Dates</h3>
754: <input type="hidden" value='' name="pres_value">
755: <input type="hidden" value='' name="pres_type">
756: <input type="hidden" value='' name="pres_marker">
757: <input type="hidden" value='$today' name=startdate>
758: <input type="hidden" value='$halfyear' name=enddate>
759: <a
760: href="javascript:pjump('date_start','Enrollment Starting Date',document.studentform.startdate.value,'start','studentform.pres','dateset');"
761: >Set Starting Date</a><p>
762:
763: <a
764: href="javascript:pjump('date_end','Enrollment Ending Date',document.studentform.enddate.value,'end','studentform.pres','dateset');"
765: >Set Ending Date</a><p>
1.18 www 766: <h3>ID/Student Number</h3>
767: <input type=checkbox name=forceid value=yes>
768: Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
1.19 www 769: (only do if you know what you are doing)<p>
1.12 www 770: <input type=button onClick="verify(this.form)" value="Enroll as student"><br>
771: <input type=hidden name=phase value=five>
1.11 www 772: ENDSENROLL
1.10 www 773: }
774:
775: # ========================================================= Menu Phase Two Drop
776:
777: sub menu_phase_two_drop {
778: my $r=shift;
1.11 www 779: my $cid=$ENV{'request.course.id'};
780: my $classlst=&Apache::lonnet::reply
781: ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'.
782: $ENV{'course.'.$cid.'.num'}.':classlist',
783: $ENV{'course.'.$cid.'.home'});
784: my %currentlist=();
785: my $now=time;
786: unless ($classlst=~/^error\:/) {
1.20 harris41 787: foreach (split(/\&/,$classlst)) {
1.11 www 788: my ($name,$value)=split(/\=/,$_);
789: my ($end,$start)=split(/\:/,
790: &Apache::lonnet::unescape($value));
791: my $active=1;
792: if (($end) && ($now>$end)) { $active=0; }
793: if ($active) {
794: $currentlist{&Apache::lonnet::unescape($name)}=1;
795: }
1.20 harris41 796: }
1.11 www 797: # ----------------------------------------------------------- Print out choices
798: &show_drop_list($r,%currentlist);
799: } else {
800: $r->print(
801: '<font color=red><h3>Could not access classlist: '.$classlst.
802: '</h3></font>');
803: }
804: }
805:
806: # =================================================== Show student list to drop
807:
808: sub show_drop_list {
809: my ($r,%currentlist)=@_;
810: my $cid=$ENV{'request.course.id'};
811:
812: $r->print('<input type=hidden name=phase value=four>');
813: $r->print('<table border=2>');
1.20 harris41 814: foreach (sort keys %currentlist) {
1.11 www 815: my ($sname,$sdom)=split(/\:/,$_);
816: my %reply=&Apache::lonnet::idrget($sdom,$sname);
817: my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid);
818: my @reply=split(/[\&\=]/,&Apache::lonnet::reply(
819: 'get:'.$sdom.':'.$sname.
820: ':environment:firstname&middlename&lastname&generation',
821: &Apache::lonnet::homeserver($sname,$sdom)));
822: $r->print(
823: '<tr><td><input type=checkbox name="drop:'.$_.'"></td><td>'.
824: $sname.'</td><td>'.$sdom.'</td><td>'.
825: $reply{$sname}.'</td><td>'.
826: &Apache::lonnet::unescape($reply[2]).' '.
827: &Apache::lonnet::unescape($reply[3]).', '.
828: &Apache::lonnet::unescape($reply[0]).' '.
829: &Apache::lonnet::unescape($reply[1]).
830: '</td><td>'.
831: $ssec."</td></tr>\n");
1.20 harris41 832: }
1.11 www 833: $r->print('</table><br>');
834: $r->print('<input type=submit value="Drop Students">');
1.10 www 835: }
836:
837: # ================================================= Drop/Add from uploaded file
838:
839: sub upfile_drop_add {
840: my $r=shift;
841:
842: &load_tmp_file($r);
843: my @studentdata=&upfile_record_sep();
844:
845: my @keyfields=split(/\,/,$ENV{'form.keyfields'});
846: my $cid=$ENV{'request.course.id'};
847:
1.4 www 848: my %fields=();
849: for (my $i=0;$i<=$ENV{'form.nfields'};$i++) {
1.10 www 850: $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
1.4 www 851: }
852: my $startdate=$ENV{'form.startdate'};
853: my $enddate=$ENV{'form.enddate'};
854: if ($startdate=~/\D/) { $startdate=''; }
855: if ($enddate=~/\D/) { $enddate=''; }
1.5 www 856: my $domain=$ENV{'form.lcdomain'};
857: my $amode='';
858: my $genpwd='';
859: if ($ENV{'form.login'} eq 'krb') {
860: $amode='krb4';
861: $genpwd=$ENV{'form.krbdom'};
862: } elsif ($ENV{'form.login'} eq 'int') {
863: $amode='internal';
864: if ((defined($ENV{'form.intpwd'})) && ($ENV{'form.intpwd'})) {
865: $genpwd=$ENV{'form.intpwd'};
866: }
1.15 albertel 867: } elsif ($ENV{'form.login'} eq 'loc') {
868: $amode='localauth';
869: if ((defined($ENV{'form.locarg'})) && ($ENV{'form.locarg'})) {
870: $genpwd=$ENV{'form.locarg'};
871: }
872: }
1.5 www 873: unless (($domain=~/\W/) || ($amode eq '')) {
874: $r->print('<h3>Enrolling Students</h3>');
1.7 www 875: my $count=0;
876: my $flushc=0;
877: my %student=();
1.5 www 878: # ----------------------------------------------------------- Get new classlist
879: # --------------------------------------------------------- Enroll new students
1.20 harris41 880: foreach (@studentdata) {
1.10 www 881: my %entries=&record_sep($_);
882:
883: unless (($entries{$fields{'username'}} eq '') ||
884: (!defined($entries{$fields{'username'}}))) {
1.4 www 885: my $fname=''; my $mname=''; my $lname=''; my $gen='';
886: if (defined($fields{'names'})) {
887: ($lname,$fname,$mname)=
1.10 www 888: ($entries{$fields{'names'}}=~/([^\,]+)\,\s*(\w+)\s*(.*)$/);
1.4 www 889: } else {
890: if (defined($fields{'fname'})) {
1.10 www 891: $fname=$entries{$fields{'fname'}};
1.4 www 892: }
893: if (defined($fields{'mname'})) {
1.10 www 894: $mname=$entries{$fields{'mname'}};
1.4 www 895: }
896: if (defined($fields{'lname'})) {
1.10 www 897: $lname=$entries{$fields{'lname'}};
1.4 www 898: }
899: if (defined($fields{'gen'})) {
1.10 www 900: $gen=$entries{$fields{'gen'}};
1.4 www 901: }
902: }
1.10 www 903: if ($entries{$fields{'username'}}=~/\W/) {
1.4 www 904: $r->print('<p><b>Unacceptable username: '.
1.10 www 905: $entries{$fields{'username'}}.' for user '.
1.4 www 906: $fname.' '.$mname.' '.$lname.' '.$gen.'</b><p>');
1.5 www 907: } else {
908: my $sec='';
1.10 www 909: my $username=$entries{$fields{'username'}};
1.5 www 910: if (defined($fields{'sec'})) {
1.10 www 911: if (defined($entries{$fields{'sec'}})) {
912: $sec=$entries{$fields{'sec'}};
1.5 www 913: }
914: }
915: my $id='';
916: if (defined($fields{'id'})) {
1.10 www 917: if (defined($entries{$fields{'id'}})) {
918: $id=$entries{$fields{'id'}};
1.5 www 919: }
920: $id=~tr/A-Z/a-z/;
921: }
922: my $password='';
923: if ($genpwd) {
924: $password=$genpwd;
925: } else {
926: if (defined($fields{'ipwd'})) {
1.10 www 927: if ($entries{$fields{'ipwd'}}) {
928: $password=$entries{$fields{'ipwd'}};
1.5 www 929: }
930: }
931: }
1.10 www 932: if ($password) {
933: &dropstudent($domain,$username,$cid,$sec);
1.5 www 934: my $reply=&Apache::lonnet::modifystudent(
935: $domain,$username,$id,$amode,$password,
1.19 www 936: $fname,$mname,$lname,$gen,$sec,$enddate,$startdate,
937: $ENV{'form.forceid'});
1.5 www 938: unless ($reply eq 'ok') {
939: $r->print(
940: "<p><b>Error enrolling $username: $reply</b><p>");
1.10 www 941: } else {
1.7 www 942: $count++; $flushc++;
943: $student{$username}=1;
1.6 www 944: $r->print('. ');
1.7 www 945: if ($flushc>15) {
946: $r->rflush;
947: $flushc=0;
948: }
1.6 www 949: }
1.5 www 950: } else {
951: $r->print(
952: "<p><b>No password for $username</b><p>");
953: }
1.4 www 954: }
955: }
1.20 harris41 956: }
1.7 www 957: $r->print('<p>Processed Students: '.$count);
1.5 www 958: # --------------------------------------------------------------- Drop students
959: if ($ENV{'form.fullup'} eq 'yes') {
960: $r->print('<h3>Dropping Students</h3>');
961: # ------------------------------------------------------- Get current classlist
962: my $classlst=&Apache::lonnet::reply
963: ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'.
964: $ENV{'course.'.$cid.'.num'}.':classlist',
965: $ENV{'course.'.$cid.'.home'});
966: my %currentlist=();
967: my $now=time;
968: unless ($classlst=~/^error\:/) {
1.20 harris41 969: foreach (split(/\&/,$classlst)) {
1.7 www 970: my ($name,$value)=split(/\=/,$_);
1.8 www 971: my ($end,$start)=split(/\:/,
1.7 www 972: &Apache::lonnet::unescape($value));
973: my $active=1;
974: if (($end) && ($now>$end)) { $active=0; }
975: if ($active) {
976: $currentlist{&Apache::lonnet::unescape($name)}=1;
977: }
1.20 harris41 978: }
1.10 www 979: # ------------------------------------------------ Now got up-to-date classlist
1.20 harris41 980: foreach (@studentdata) {
1.10 www 981: my %entries=&record_sep($_);
982: unless (($entries{$fields{'username'}} eq '') ||
983: (!defined($entries{$fields{'username'}}))) {
984: delete($currentlist{
985: $entries{$fields{'username'}}.':'.
986: $domain});
987: }
1.20 harris41 988: }
1.10 www 989: # ----------------------------------------------------------- Print out choices
1.11 www 990: &show_drop_list($r,%currentlist);
1.5 www 991: } else {
992: $r->print(
993: '<font color=red><h3>Could not access classlist: '.$classlst.
994: '</h3></font>');
995: }
996: }
997: # ------------------------------------------------------------------------ Done
1.10 www 998:
999: }
1000: }
1001:
1.11 www 1002: # ================================================================== Phase four
1003:
1004: sub drop_student_list {
1005: my $r=shift;
1006: my $count=0;
1.20 harris41 1007: foreach (keys %ENV) {
1.11 www 1008: if ($_=~/^form\.drop\:/) {
1009: my ($dummy,$uname,$udom)=split(/\:/,$_);
1010: &dropstudent($udom,$uname,$ENV{'request.course.id'});
1011: $r->print('Dropped '.$uname.' at '.$udom.'<br>');
1012: $count++;
1013: }
1.20 harris41 1014: }
1.11 www 1015: $r->print('<p><b>Dropped '.$count.' student(s).</b>');
1016: $r->print('<p>Re-enrollment will re-activate data.');
1017: }
1018:
1.10 www 1019: # ================================================================ Main Handler
1020:
1021: sub handler {
1022: my $r=shift;
1023:
1024: if ($r->header_only) {
1025: $r->content_type('text/html');
1026: $r->send_http_header;
1027: return OK;
1028: }
1029:
1030: # ----------------------------------------------------- Needs to be in a course
1031:
1032: if (($ENV{'request.course.fn'}) &&
1033: (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'}))) {
1034:
1035: # ------------------------------------------------------------------ Start page
1036: $r->content_type('text/html');
1037: $r->send_http_header;
1038: &header($r);
1039:
1040: # --------------------------------------------------- Phase one, initial screen
1041: unless ($ENV{'form.phase'}) {
1042: &menu_phase_one($r);
1043: }
1044: # ------------------------------------------------------------------- Phase two
1045: if ($ENV{'form.phase'} eq 'two') {
1046: if ($ENV{'form.fileupload'}) {
1047: &menu_phase_two_upload($r);
1048: } elsif ($ENV{'form.enroll'}) {
1049: &menu_phase_two_enroll($r);
1050: } elsif ($ENV{'form.drop'}) {
1051: &menu_phase_two_drop($r);
1052: }
1053: }
1054:
1055:
1056:
1057:
1058: # ----------------------------------------------------------------- Phase three
1059: if ($ENV{'form.phase'} eq 'three') {
1060: if ($ENV{'form.datatoken'}) {
1061: &upfile_drop_add($r);
1.2 www 1062: }
1.11 www 1063: }
1064: # ------------------------------------------------------------------ Phase four
1065: if ($ENV{'form.phase'} eq 'four') {
1066: &drop_student_list($r);
1.12 www 1067: }
1068: # ------------------------------------------------------------------ Phase four
1069: if ($ENV{'form.phase'} eq 'five') {
1070: &enroll_single_student($r);
1.2 www 1071: }
1072: # ------------------------------------------------------------------------- End
1.1 www 1073: $r->print('</form></body></html>');
1074: } else {
1075: # ----------------------------- Not in a course, or not allowed to modify parms
1076: $ENV{'user.error.msg'}=
1077: "/adm/dropadd:cst:0:0:Cannot drop or add students";
1078: return HTTP_NOT_ACCEPTABLE;
1079: }
1080: return OK;
1081: }
1082:
1083: 1;
1084: __END__
1085:
1086:
1087:
1088:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>