More racketizations

This commit is contained in:
Eli Barzilay 2010-09-12 03:22:03 -04:00
parent d0a2d617c8
commit d32400dd76
30 changed files with 367 additions and 369 deletions

View File

@ -1,9 +1,9 @@
#lang scheme/base #lang racket/base
(require (for-syntax scheme/base) "utils.rkt" (require (for-syntax racket/base) "utils.rkt"
scheme/file scheme/class mred) racket/file racket/class racket/gui/base)
(provide (except-out (all-from-out scheme/base) #%module-begin) (provide (except-out (all-from-out racket/base) #%module-begin)
(all-from-out "utils.rkt")) (all-from-out "utils.rkt"))
(provide (rename-out [module-begin~ #%module-begin])) (provide (rename-out [module-begin~ #%module-begin]))
@ -93,7 +93,7 @@
;; * snip->text is used earlier in the process, where comment-box text is still ;; * snip->text is used earlier in the process, where comment-box text is still
;; available ;; available
(require framework) ; for drscheme snips, used below (require framework) ; for drracket snips, used below
;; input-port->text-input-port : input-port (any -> any) -> input-port ;; input-port->text-input-port : input-port (any -> any) -> input-port
;; the `filter' function is applied to special values; the filter result is ;; the `filter' function is applied to special values; the filter result is

View File

@ -1,9 +1,9 @@
#lang racket/base #lang racket/base
(require mzlib/thread (require mzlib/thread
scheme/port racket/port
openssl openssl
scheme/file racket/file
"private/logger.rkt" "private/logger.rkt"
"private/config.rkt" "private/config.rkt"
"private/lock.rkt" "private/lock.rkt"

View File

@ -1,4 +1,4 @@
#lang scheme/gui #lang racket/gui
(require htdp/error lang/prim) (require htdp/error lang/prim)

View File

@ -1,4 +1,4 @@
#lang scheme/gui #lang racket/gui
(require htdp/error lang/prim) (require htdp/error lang/prim)

View File

@ -1,6 +1,6 @@
#lang scheme/base #lang racket/base
(require scheme/file) (require racket/file)
;; This module should be invoked when we're in the server directory ;; This module should be invoked when we're in the server directory
(provide server-dir) (provide server-dir)

View File

@ -1,4 +1,4 @@
#lang scheme/base #lang racket/base
(require "config.rkt" "logger.rkt" "reloadable.rkt") (require "config.rkt" "logger.rkt" "reloadable.rkt")

View File

@ -1,4 +1,4 @@
#lang scheme/base #lang racket/base
(provide wait-for-lock) (provide wait-for-lock)

View File

@ -1,6 +1,6 @@
#lang scheme/base #lang racket/base
(require "config.rkt" scheme/date scheme/port) (require "config.rkt" racket/date racket/port)
(provide current-session) (provide current-session)
(define current-session (make-parameter #f)) (define current-session (make-parameter #f))

View File

@ -1,5 +1,5 @@
#lang scheme/base #lang racket/base
(require (prefix-in mz: file/md5)) (require (prefix-in r: file/md5))
(define (md5 s) (define (md5 s)
(bytes->string/latin-1 (mz:md5 (string->bytes/utf-8 s)))) (bytes->string/latin-1 (r:md5 (string->bytes/utf-8 s))))
(provide md5) (provide md5)

View File

@ -1,4 +1,4 @@
#lang scheme/base #lang racket/base
(require syntax/moddep "logger.rkt") (require syntax/moddep "logger.rkt")
@ -15,7 +15,7 @@
(with-handlers ([exn? (lambda (e) (with-handlers ([exn? (lambda (e)
(log-line "error, module not reloaded (~a)" (log-line "error, module not reloaded (~a)"
(exn-message e)))]) (exn-message e)))])
(namespace-require '(only scheme module #%top-interaction)) (namespace-require '(only racket module #%top-interaction))
(load/use-compiled path))))) (load/use-compiled path)))))
;; pulls out a value from a module, reloading the module if its source file was ;; pulls out a value from a module, reloading the module if its source file was

View File

@ -1,4 +1,4 @@
#lang scheme/base #lang racket/base
(provide current-run-status-box set-run-status (provide current-run-status-box set-run-status
current-messenger message) current-messenger message)

View File

@ -1,13 +1,13 @@
#lang scheme/base #lang racket/base
(define default-context-length (error-print-context-length)) (define default-context-length (error-print-context-length))
;; This code has parts that are copied from `serve/servlet' in ;; This code has parts that are copied from `serve/servlet' in
;; "web-server/servlet-env.ss", and parts from `serve/launch/wait' in ;; "web-server/servlet-env.rkt", and parts from `serve/launch/wait' in
;; "web-server/servlet-dispatch.ss" ;; "web-server/servlet-dispatch.rkt"
(require scheme/unit (require racket/unit
scheme/async-channel racket/async-channel
web-server/web-server web-server/web-server
web-server/servlet-dispatch web-server/servlet-dispatch
web-server/managers/lru web-server/managers/lru
@ -106,7 +106,7 @@
(* 12 1024 1024)))) (* 12 1024 1024))))
;; This can be used to serve html content too; doesn't make sense now, ;; This can be used to serve html content too; doesn't make sense now,
;; since the servlet will be used for all requests, and it never calls ;; since the servlet will be used for all requests, and it never calls
;; (next-dispatcher). (See "servlet-env.ss" for the needed `require's.) ;; (next-dispatcher). (See "servlet-env.rkt" for the needed `require's.)
;; (files:make ;; (files:make
;; #:url->path (fsmap:make-url->path (build-path server-dir "htdocs"))) ;; #:url->path (fsmap:make-url->path (build-path server-dir "htdocs")))
;; (lift:make (send-error "File not found" (lambda () "/"))) ;; (lift:make (send-error "File not found" (lambda () "/")))

View File

@ -1,6 +1,6 @@
#lang scheme/base #lang racket/base
(require scheme/sandbox) (require racket/sandbox)
(provide (all-from-out scheme/sandbox)) (provide (all-from-out racket/sandbox))
;; no input/output ;; no input/output
(sandbox-input #f) (sandbox-input #f)
@ -20,6 +20,7 @@
,@(if gui? '(mrlib/cache-image-snip) '())))) ,@(if gui? '(mrlib/cache-image-snip) '()))))
;; local overrides ;; local overrides
(require racket/runtime-path)
(define-runtime-path overrides "overridden-collects")
(sandbox-override-collection-paths (sandbox-override-collection-paths
(cons (build-path (collection-path "handin-server") "overridden-collects") (cons overrides (sandbox-override-collection-paths)))
(sandbox-override-collection-paths)))

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title[#:style 'toc]{Checker Utilities} @title[#:style 'toc]{Checker Utilities}
@ -10,20 +10,19 @@ order):
@itemize[ @itemize[
@item{@schememodname[scheme/sandbox]: contains basic sandbox @item{@racketmodname[racket/sandbox]: is the basic sandbox
evaluation utilities. This is in MzLib since it can be used evaluation code, which is the basic functionality checkers build on.}
independently.}
@item{@schememodname[handin-server/sandbox]: contains a wrapper that @item{@racketmodname[handin-server/sandbox]: contains a wrapper that
configures MzLib's sandbox for the handin server.} configures the Racket sandbox for the handin server.}
@item{@schememodname[handin-server/utils]: contains additional @item{@racketmodname[handin-server/utils]: contains additional
utilities for dealing with handin submissions, as well as a few utilities for dealing with handin submissions, as well as a few
helpers for testing code.} helpers for testing code.}
@item{@schememodname[handin-server/checker]: automates the task of @item{@racketmodname[handin-server/checker]: automates the task of
creating a checker function (in creating a checker function (in
@filepath{<active-assignment>/checker.ss} modules) to cope with @filepath{<active-assignment>/checker.rkt} modules) to cope with
common submission situations.}] common submission situations.}]
The following sections describe each of these modules. The following sections describe each of these modules.

View File

@ -1,20 +1,20 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@(define textoption @(define textoption
@t{(Effective only when saving a textual version of @t{(Effective only when saving a textual version of
the submission files: when @scheme[:create-text?] is on.)}) the submission files: when @racket[:create-text?] is on.)})
@title{Checker} @title{Checker}
@defmodulelang[handin-server/checker]{ @defmodulelang[handin-server/checker]{
The @schememodname[handin-server/checker] module provides a The @racketmodname[handin-server/checker] module provides a
higher-level of utilities, helpful in implementing `checker' functions higher-level of utilities, helpful in implementing `checker' functions
that are intended for a more automated system. This module is a that are intended for a more automated system. This module is a
language module---a typical checker that uses it looks like this: language module---a typical checker that uses it looks like this:
@schemeblock[ @racketblock[
(module checker handin-server/checker (module checker handin-server/checker
(check: :language '(special intermediate) (check: :language '(special intermediate)
:users pairs-or-singles-with-warning :users pairs-or-singles-with-warning
@ -34,7 +34,7 @@ language module---a typical checker that uses it looks like this:
Constructs (and provides) an appropriate checker function, using Constructs (and provides) an appropriate checker function, using
keywords to customize features that you want it to have. The body of keywords to customize features that you want it to have. The body of
the checker (following the keywords) can contain arbitrary code, using the checker (following the keywords) can contain arbitrary code, using
utility functions from @schememodname[handin-server/utils], as well as utility functions from @racketmodname[handin-server/utils], as well as
additional ones that are defined below. Submission files are arriving additional ones that are defined below. Submission files are arriving
to the handin server in binary form (in the GRacket format that is used to the handin server in binary form (in the GRacket format that is used
to store text and other objects like images), and a number of these to store text and other objects like images), and a number of these
@ -42,70 +42,70 @@ options involve genrating a textual version of this file. The purpose
of these options is to have these text files integrate easily into a of these options is to have these text files integrate easily into a
course framework for grading, based on these text files.} course framework for grading, based on these text files.}
Keywords for configuring @scheme[check:]: Keywords for configuring @racket[check:]:
@itemize[ @itemize[
@item{@indexed-scheme[:users]---specification of users that are @item{@indexed-racket[:users]---specification of users that are
acceptable for submission. Can be either a list of user lists, each acceptable for submission. Can be either a list of user lists, each
representing a known team, or procedure which will accept a list of representing a known team, or procedure which will accept a list of
users and throw an exception if they are unacceptable. The default users and throw an exception if they are unacceptable. The default
is to accept only single-user submissions. The is to accept only single-user submissions. The
@scheme[pairs-or-singles-with-warning] procedure is a useful value @racket[pairs-or-singles-with-warning] procedure is a useful value
for pair submission where the pairs are unknown.} for pair submission where the pairs are unknown.}
@item{@indexed-scheme[:eval?]---whether submissions should be @item{@indexed-racket[:eval?]---whether submissions should be
evaluated. Defaults to @scheme[#t]. Note that if it is specified evaluated. Defaults to @racket[#t]. Note that if it is specified
as @scheme[#f], then the checker body will not be able to run any as @racket[#f], then the checker body will not be able to run any
tests on the code, unless it contains code that performs some tests on the code, unless it contains code that performs some
evaluation (e.g., using the facilities of evaluation (e.g., using the facilities of
@schememodname[handin-server/utils]).} @racketmodname[handin-server/utils]).}
@item{@indexed-scheme[:language]---the language that is used for @item{@indexed-racket[:language]---the language that is used for
evaluating submissions, same as the @scheme[_language] argument for evaluating submissions, same as the @racket[_language] argument for
@scheme[make-evaluator] (see @schememodname[handin-server/sandbox]), @racket[make-evaluator] (see @racketmodname[handin-server/sandbox]),
except that if the value ls @racket[(list 'module _spec)], except that if the value ls @racket[(list 'module _spec)],
then @racket[make-module-evaluator] is used with @racket[_spec] then @racket[make-module-evaluator] is used with @racket[_spec]
as its @racket[#:language] argument. as its @racket[#:language] argument.
There is no default for this, so it must be set or an error is There is no default for this, so it must be set or an error is
raised. (See @scheme[call-with-evaluator/submission] for further raised. (See @racket[call-with-evaluator/submission] for further
details.)} details.)}
@item{@indexed-scheme[:requires]---paths for additional libraries to @item{@indexed-racket[:requires]---paths for additional libraries to
require for evaluating the submission, same as the require for evaluating the submission, same as the
@scheme[_requires] argument for @scheme[make-evaluator] (see @racket[_requires] argument for @racket[make-evaluator] (see
@schememodname[handin-server/sandbox]). This defaults to null---no @racketmodname[handin-server/sandbox]). This defaults to null---no
teachpacks. Note: if a module language is used (See teachpacks. Note: if a module language is used (See
@scheme[call-with-evaluator/submission] for further details), it is @racket[call-with-evaluator/submission] for further details), it is
passed as the @scheme[_allow-read] argument.} passed as the @racket[_allow-read] argument.}
@item{@indexed-scheme[:teachpacks]---an alternative name for @item{@indexed-racket[:teachpacks]---an alternative name for
@scheme[:requires], kept for legacy checkers.} @racket[:requires], kept for legacy checkers.}
@item{@indexed-scheme[:create-text?]---if true, then a textual version @item{@indexed-racket[:create-text?]---if true, then a textual version
of the submission is saved as @filepath{text.scm} in a of the submission is saved as @filepath{text.rkt} in a
@filepath{grading} subdirectory (or any suffix that is specified by @filepath{grading} subdirectory (or any suffix that is specified by
@scheme[:output] below, for example @filepath{hw.java} is converted @racket[:output] below, for example @filepath{hw.java} is converted
into a textual @filepath{grading/text.java}). This is intended for into a textual @filepath{grading/text.java}). This is intended for
printouts and grading, and is in a subdirectory so students will not printouts and grading, and is in a subdirectory so students will not
see it on the status web server. Defaults to @scheme[#t].} see it on the status web server. Defaults to @racket[#t].}
@item{@indexed-scheme[:textualize?]---if true, then all submissions @item{@indexed-racket[:textualize?]---if true, then all submissions
are converted to text, trying to convert objects like images and are converted to text, trying to convert objects like images and
comment boxes to some form of text. Defaults to @scheme[#f], comment boxes to some form of text. Defaults to @racket[#f],
meaning that an exception is raised for submissions that are not all meaning that an exception is raised for submissions that are not all
text. @textoption text. @textoption
This flag is effective only when saving a textual version of the This flag is effective only when saving a textual version of the
submission files --- when @scheme[:create-text?] is on. The submission files --- when @racket[:create-text?] is on. The
possible configurations are: possible configurations are:
@itemize[ @itemize[
@item{@scheme[:create-text?] is on and @scheme[:textualize?] is off @item{@racket[:create-text?] is on and @racket[:textualize?] is off
(the default) --- in this case a text version of submissions is (the default) --- in this case a text version of submissions is
created, and submissions must contain only plain text. The text created, and submissions must contain only plain text. The text
file has the same semantics of the submission and can be used to file has the same semantics of the submission and can be used to
run student code.} run student code.}
@item{@scheme[:create-text?] is off --- allowing submissions that @item{@racket[:create-text?] is off --- allowing submissions that
contain non-textual objects, but no text file is created so contain non-textual objects, but no text file is created so
grading and testing must be done using DrRacket (because the saved grading and testing must be done using DrRacket (because the saved
submission is always in binary format).} submission is always in binary format).}
@ -114,81 +114,81 @@ Keywords for configuring @scheme[check:]:
usable as code since objects like images cannot be represented in usable as code since objects like images cannot be represented in
plain text.}]} plain text.}]}
@item{@indexed-scheme[:untabify?]---if true, then tabs are converted @item{@indexed-racket[:untabify?]---if true, then tabs are converted
to spaces, assuming a standard tab width of 8 places. This is to spaces, assuming a standard tab width of 8 places. This is
needed for a correct computation of line lengths, but note that needed for a correct computation of line lengths, but note that
DrRacket does not insert tabs in Scheme mode. Defaults to DrRacket does not insert tabs in Scheme mode. Defaults to
@scheme[#t]. @textoption} @racket[#t]. @textoption}
@item{@indexed-scheme[:maxwidth]---a number that specifies maximum @item{@indexed-racket[:maxwidth]---a number that specifies maximum
line lengths for submissions (a helpful feature for reading student line lengths for submissions (a helpful feature for reading student
code). Defaults to 79. This feature can be disabled if set to code). Defaults to 79. This feature can be disabled if set to
@scheme[#f]. @textoption} @racket[#f]. @textoption}
@item{@indexed-scheme[:output]---the name of the original handin file @item{@indexed-racket[:output]---the name of the original handin file
(unrelated to the text-converted files). Defaults to (unrelated to the text-converted files). Defaults to
@filepath{hw.rkt}. (The suffix changes the defaults of @filepath{hw.rkt}. (The suffix changes the defaults of
@scheme[:markup-prefix] and @scheme[:prefix-re].) Can be @racket[:markup-prefix] and @racket[:prefix-re].) Can be
@scheme[#f] for removing the original file after processing. The @racket[#f] for removing the original file after processing. The
file is always stored in GRacket's binary format.} file is always stored in GRacket's binary format.}
@item{@indexed-scheme[:multi-file]---by default, this is set to @item{@indexed-racket[:multi-file]---by default, this is set to
@scheme[#f], which means that only DrRacket is used to send @racket[#f], which means that only DrRacket is used to send
submissions as usual. See @secref{multi-file} for setting up submissions as usual. See @secref{multi-file} for setting up
multi-file submissions.} multi-file submissions.}
@item{@indexed-scheme[:names-checker]---used for multi-file @item{@indexed-racket[:names-checker]---used for multi-file
submissions; see @secref{multi-file} for details.} submissions; see @secref{multi-file} for details.}
@item{@indexed-scheme[:markup-prefix]---used as the prefix for @item{@indexed-racket[:markup-prefix]---used as the prefix for
@scheme[:student-lines] and @scheme[:extra-lines] below. The @racket[:student-lines] and @racket[:extra-lines] below. The
default is @scheme[";;> "] or @scheme["//> "], depending on the default is @racket[";;> "] or @racket["//> "], depending on the
suffix of @scheme[:output] above. Note: if you change this, make suffix of @racket[:output] above. Note: if you change this, make
sure to change @scheme[:prefix-re] too. @textoption} sure to change @racket[:prefix-re] too. @textoption}
@item{@indexed-scheme[:prefix-re]---used to identify lines with markup @item{@indexed-racket[:prefix-re]---used to identify lines with markup
(@scheme[";>"] or @scheme["//>"] etc), so students cannot fool the (@racket[";>"] or @racket["//>"] etc), so students cannot fool the
system by writing marked-up code. The default is @scheme[";>"] or system by writing marked-up code. The default is @racket[";>"] or
@scheme["//>"], depending on the suffix of :output above. @racket["//>"], depending on the suffix of :output above.
@textoption} @textoption}
@item{@indexed-scheme[:student-line]---when a submission is converted @item{@indexed-racket[:student-line]---when a submission is converted
to text, it begins with lines describing the students that have to text, it begins with lines describing the students that have
submitted it; this is used to specify the format of these lines. It submitted it; this is used to specify the format of these lines. It
is a string with holes that @scheme[user-substs] fills out. is a string with holes that @racket[user-substs] fills out.
The default is @scheme["Student: {username} ({Full Name} <{Email}>)"], The default is @racket["Student: {username} ({Full Name} <{Email}>)"],
which requires @scheme["Full Name"] and @scheme["Email"] entries in which requires @racket["Full Name"] and @racket["Email"] entries in
the server's extra-fields configuration. These lines are prefixed the server's extra-fields configuration. These lines are prefixed
with @scheme[";;> "] or the prefix specified by with @racket[";;> "] or the prefix specified by
@scheme[:makup-prefix] above. @textoption} @racket[:makup-prefix] above. @textoption}
@item{@indexed-scheme[:extra-lines]---a list of lines to add after the @item{@indexed-racket[:extra-lines]---a list of lines to add after the
student lines, all with a @scheme[";;> "] or :markup-prefix too. student lines, all with a @racket[";;> "] or :markup-prefix too.
Defaults to a single line: Defaults to a single line:
@scheme["Maximum points for this assignment: <+100>"]. (Can use @racket["Maximum points for this assignment: <+100>"]. (Can use
@scheme["{submission}"] for the submission directory.) See also @racket["{submission}"] for the submission directory.) See also
@scheme[add-header-line!]. @textoption} @racket[add-header-line!]. @textoption}
@item{@indexed-scheme[:user-error-message]---a string that is used to @item{@indexed-racket[:user-error-message]---a string that is used to
report an error that occurred during evaluation of the submitted report an error that occurred during evaluation of the submitted
code (not during additional tests). It can be a plain string which code (not during additional tests). It can be a plain string which
will be used as the error message, or a string with single a will be used as the error message, or a string with single a
@scheme["~a"] (or @scheme["~s"], @scheme["~v"], @scheme["~e"], @racket["~a"] (or @racket["~s"], @racket["~v"], @racket["~e"],
or @scheme["~.a"] etc) that or @racket["~.a"] etc) that
will be used as a format string with the actual error message. The will be used as a format string with the actual error message. The
default is @scheme["Error in your code --\n~a"]. Useful examples of default is @racket["Error in your code --\n~a"]. Useful examples of
these messages: these messages:
@scheme["There is an error in your program, hit \"Run\" to debug"] @racket["There is an error in your program, hit \"Run\" to debug"]
@scheme["There is an error in your program:\n----\n~a\n----\nHit \"Run\" and debug your code."] @racket["There is an error in your program:\n----\n~a\n----\nHit \"Run\" and debug your code."]
Alternatively, the value can be a procedure that will be invoked Alternatively, the value can be a procedure that will be invoked
with the error message. The procedure can do anything it wants, and with the error message. The procedure can do anything it wants, and
if it does not raise an exception, then the checker will proceed as if it does not raise an exception, then the checker will proceed as
usual. For example: usual. For example:
@schemeblock[ @racketblock[
(lambda (msg) (lambda (msg)
(add-header-line! "Erroneous submission!") (add-header-line! "Erroneous submission!")
(add-header-line! (format " --> ~a" msg)) (add-header-line! (format " --> ~a" msg))
@ -205,42 +205,42 @@ Keywords for configuring @scheme[check:]:
(Note that if you do this, then additional tests should be adjusted (Note that if you do this, then additional tests should be adjusted
to not raise an exception too.)} to not raise an exception too.)}
@item{@indexed-scheme[:value-printer]---if specified, this will be @item{@indexed-racket[:value-printer]---if specified, this will be
used for @scheme[current-value-printer].} used for @racket[current-value-printer].}
@item{@indexed-scheme[:coverage?]---collect coverage information when @item{@indexed-racket[:coverage?]---collect coverage information when
evaluating the submission. This will cause an error if some input evaluating the submission. This will cause an error if some input
is not covered. This check happens after checker tests are run, but is not covered. This check happens after checker tests are run, but
the information is collected and stored before, so checker tests do the information is collected and stored before, so checker tests do
not change the result. Also, you can use the @scheme[!all-covered] not change the result. Also, you can use the @racket[!all-covered]
procedure in the checker before other tests, if you want that procedure in the checker before other tests, if you want that
feedback earlier.}] feedback earlier.}]
Within the body of @scheme[check:], @scheme[users] and Within the body of @racket[check:], @racket[users] and
@scheme[submission] will be bound to the checker arguments---a @racket[submission] will be bound to the checker arguments---a
(sorted) list of usernames and the submission as a byte string. In (sorted) list of usernames and the submission as a byte string. In
addition to the functionality below, you can use addition to the functionality below, you can use
@scheme[(!eval _expr)] (or @scheme[((submission-eval) '_expr)]) to @racket[(!eval _expr)] (or @racket[((submission-eval) '_expr)]) to
evaluate expressions in the submitted code context, and you can use evaluate expressions in the submitted code context, and you can use
@scheme[(with-submission-bindings (id ...) body ...)] to evaluate the @racket[(with-submission-bindings (id ...) body ...)] to evaluate the
body when @scheme[id]'s are bound to their values from the submission body when @racket[id]'s are bound to their values from the submission
code.} code.}
@deftogether[(@defform[(pre: body ...)] @deftogether[(@defform[(pre: body ...)]
@defform[(post: body ...)])]{ @defform[(post: body ...)])]{
These two macros define a pre- and a post-checker. In their bodies, These two macros define a pre- and a post-checker. In their bodies,
@scheme[_users] and @scheme[_submission] are bound as in @racket[_users] and @racket[_submission] are bound as in
@scheme[check:], but there is nothing else special about these. See @racket[check:], but there is nothing else special about these. See
the description of the @scheme[pre-checker] and the description of the @racket[pre-checker] and
@scheme[post-checker] values for what can be done with these, and @racket[post-checker] values for what can be done with these, and
note that the check for valid users is always first. An example for note that the check for valid users is always first. An example for
a sophisticated @scheme[post:] block is below---it will first a sophisticated @racket[post:] block is below---it will first
disable timeouts for this session, then it will send a email with a disable timeouts for this session, then it will send a email with a
submission receipt, with CC to the TA (assuming a single TA), and submission receipt, with CC to the TA (assuming a single TA), and
pop-up a message telling the student about it: pop-up a message telling the student about it:
@schemeblock[ @racketblock[
(require net/sendmail) (require net/sendmail)
(post: (post:
(define info (define info
@ -273,25 +273,25 @@ code.}
Returns a user information given a username. The returned Returns a user information given a username. The returned
information is a list of strings that corresponds to the configured information is a list of strings that corresponds to the configured
@scheme[extra-fields].} @racket[extra-fields].}
@defproc[(user-substs [user string?] [fmt string?]) string]{ @defproc[(user-substs [user string?] [fmt string?]) string]{
Uses the mappings in @scheme[user-data] to substitute user Uses the mappings in @racket[user-data] to substitute user
information for substrings of the form ``@tt{{some-field-name}}'' in information for substrings of the form ``@tt{{some-field-name}}'' in
@scheme[fmt]. This procedure signals an error if a field name is @racket[fmt]. This procedure signals an error if a field name is
missing in the user data. Also, ``@tt{{username}}'' will always be missing in the user data. Also, ``@tt{{username}}'' will always be
replaced by the username and ``@tt{{submission}}'' by the current replaced by the username and ``@tt{{submission}}'' by the current
submission directory. submission directory.
This is used to process the @scheme[:student-line] value in the This is used to process the @racket[:student-line] value in the
checker, but it is provided for additional uses. See the above checker, but it is provided for additional uses. See the above
sample code for @scheme[post:] for using this procedure.} sample code for @racket[post:] for using this procedure.}
@defproc[(pairs-or-singles-with-warning [users (listof string?)]) @defproc[(pairs-or-singles-with-warning [users (listof string?)])
any]{ any]{
Intended for use as the @scheme[:users] entry in a checker. It will Intended for use as the @racket[:users] entry in a checker. It will
do nothing if there are two users, and throw an error if there are do nothing if there are two users, and throw an error if there are
more. If there is a single user, then the user will be asked to more. If there is a single user, then the user will be asked to
verify a single submission. If the student cancels, then an verify a single submission. If the student cancels, then an
@ -313,21 +313,21 @@ code.}
specified in this file. Furthermore, if this file is modified, the specified in this file. Furthermore, if this file is modified, the
new contents will be used immediately, so there is no need to new contents will be used immediately, so there is no need to
restart the server of you want to change student teams. (But restart the server of you want to change student teams. (But
remember that if you change @scheme[("foo" "bar")] to remember that if you change @racket[("foo" "bar")] to
@scheme[("foo" "baz")], and there is already a @filepath{bar+foo} @racket[("foo" "baz")], and there is already a @filepath{bar+foo}
submission directory, then the system will not allow ``@tt{foo}'' to submission directory, then the system will not allow ``@tt{foo}'' to
submit with ``@tt{bar}''.)} submit with ``@tt{bar}''.)}
@defproc[(add-header-line! [line string?]) void?]{ @defproc[(add-header-line! [line string?]) void?]{
During the checker operation, can be used to add header lines to the During the checker operation, can be used to add header lines to the
text version of the submitted file (in addition to the text version of the submitted file (in addition to the
@scheme[:extra-lines] setting). It will not have an effect if @racket[:extra-lines] setting). It will not have an effect if
@scheme[:create-text?] is false.} @racket[:create-text?] is false.}
@defproc[(procedure/arity? [proc procedure?] [arity number?]) @defproc[(procedure/arity? [proc procedure?] [arity number?])
boolean?]{ boolean?]{
Returns @scheme[#t] if @scheme[proc] is a procedure that accepts Returns @racket[#t] if @racket[proc] is a procedure that accepts
@scheme[arity] arguments.} @racket[arity] arguments.}
@defform[(!defined id ...)]{ @defform[(!defined id ...)]{
Checks that the given identifiers are defined in the (evaluated) Checks that the given identifiers are defined in the (evaluated)
@ -340,21 +340,21 @@ code.}
identifier is bound to a syntax.} identifier is bound to a syntax.}
@defform[(!syntax id arity)]{ @defform[(!syntax id arity)]{
Checks that @scheme[id] is defined, and is bound as a macro.} Checks that @racket[id] is defined, and is bound as a macro.}
@defform[(!procedure id arity)]{ @defform[(!procedure id arity)]{
Checks that @scheme[id] is defined, and is bound to a procedure.} Checks that @racket[id] is defined, and is bound to a procedure.}
@defform[(!procedure* expr arity)]{ @defform[(!procedure* expr arity)]{
Similar to @scheme[!procedure] but omits the defined check, making Similar to @racket[!procedure] but omits the defined check, making
it usable with any expression, which is then evaluated in the it usable with any expression, which is then evaluated in the
submission context.} submission context.}
@deftogether[(@defform[(!integer id)] @deftogether[(@defform[(!integer id)]
@defform[(!integer* expr)])]{ @defform[(!integer* expr)])]{
Similar to @scheme[!procedure] and @scheme[!procedure*] for Similar to @racket[!procedure] and @racket[!procedure*] for
integers.} integers.}
@deftogether[( @deftogether[(
@ -364,42 +364,42 @@ code.}
@defform[(!test/exn expr)] @defform[(!test/exn expr)]
)]{ )]{
The first @scheme[!test] form checks that the given expression The first @racket[!test] form checks that the given expression
evaluates to a non-@scheme[#f] value in the submission context, evaluates to a non-@racket[#f] value in the submission context,
throwing an error otherwise. The second form compares the result of throwing an error otherwise. The second form compares the result of
evaluation, requiring it to be equal to @scheme[result]. The third evaluation, requiring it to be equal to @racket[result]. The third
allows specifying an equality procedure. The @scheme[!test/exn] form allows specifying an equality procedure. The @racket[!test/exn] form
checks that the given expression throws an @scheme[exn:fail?] error, checks that the given expression throws an @racket[exn:fail?] error,
throwing an error otherwise. throwing an error otherwise.
For the latter two @scheme[!test] forms, note that the For the latter two @racket[!test] forms, note that the
@scheme[result] and @scheme[equal?] forms are @italic{not} evaluated @racket[result] and @racket[equal?] forms are @italic{not} evaluated
in the submission context.} in the submission context.}
@defform[(!eval expr)]{ @defform[(!eval expr)]{
Evaluate an arbitrary expession in the submission context. This is Evaluate an arbitrary expession in the submission context. This is
a simple shorthand for @scheme[((submission-eval) `expr)].} a simple shorthand for @racket[((submission-eval) `expr)].}
@defproc*[([(!all-covered) void?] @defproc*[([(!all-covered) void?]
[(!all-covered [proc (string? . -> . any)]) void?])]{ [(!all-covered [proc (string? . -> . any)]) void?])]{
When coverage information is enabled (see @scheme[:coverage?] When coverage information is enabled (see @racket[:coverage?]
above), checks the collected coverage information and throws an above), checks the collected coverage information and throws an
error with source information if some code is left uncovered. If error with source information if some code is left uncovered. If
@scheme[proc] is provided, it is applied to a string argument that @racket[proc] is provided, it is applied to a string argument that
describes the location of the uncovered expression describes the location of the uncovered expression
(@scheme["<line>:<col>"], @scheme["#<char-pos>"], or (@racket["<line>:<col>"], @racket["#<char-pos>"], or
@scheme["(unknown position)"]) instead of throwing an error. The @racket["(unknown position)"]) instead of throwing an error. The
collected information includes only execution coverage by submission collected information includes only execution coverage by submission
code, excluding additional checker tests. You do not have to call code, excluding additional checker tests. You do not have to call
this explicitly---it is called at the end of the process this explicitly---it is called at the end of the process
automatically when @scheme[:coverage?] is enabled. It is made automatically when @racket[:coverage?] is enabled. It is made
available so you can call it earlier (e.g., before testing) to show available so you can call it earlier (e.g., before testing) to show
clients a coverage error first, or if you want to avoid an error. clients a coverage error first, or if you want to avoid an error.
For example, you can do this: For example, you can do this:
@schemeblock[ @racketblock[
(!all-covered (!all-covered
(lambda (where) (lambda (where)
(case (message (string-append (case (message (string-append

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Client Customization} @title{Client Customization}
@ -9,10 +9,10 @@ collection directory. The new name should describe your class
uniquely. For example, @filepath{uu-cs1410} is a good name for CS uniquely. For example, @filepath{uu-cs1410} is a good name for CS
1410 at the University of Utah.} 1410 at the University of Utah.}
@item{Edit the first three definitions of @filepath{info.ss} in your @item{Edit the first three definitions of @filepath{info.rkt} in your
renamed client collection: renamed client collection:
@itemize[ @itemize[
@item{For @scheme[name], choose a name for the handin tool as it @item{For @racket[name], choose a name for the handin tool as it
will appear in DrRacket's interface (e.g., the @onscreen{XXX} for will appear in DrRacket's interface (e.g., the @onscreen{XXX} for
the @onscreen{Manage XXX Handin Account...} menu item). Again, the @onscreen{Manage XXX Handin Account...} menu item). Again,
make the name specific to the course, in case a student installs make the name specific to the course, in case a student installs
@ -20,16 +20,16 @@ uniquely. For example, @filepath{uu-cs1410} is a good name for CS
part of the name, since @onscreen{Handin} is always added for part of the name, since @onscreen{Handin} is always added for
button and menu names.} button and menu names.}
@item{Uncomment the definitions of @scheme[tools], @item{Uncomment the definitions of @racket[tools],
@scheme[tool-names], and @scheme[tool-icons]. (But leave the @racket[tool-names], and @racket[tool-icons]. (But leave the
latter field's definition as @filepath{icon.png}.)} latter field's definition as @filepath{icon.png}.)}
@item{For @scheme[server:port], uncomment the line, and use the @item{For @racket[server:port], uncomment the line, and use the
hostname and port where the server will be running to accept hostname and port where the server will be running to accept
handin submissions.}] handin submissions.}]
Optionally uncomment and edit the next two definitions, Optionally uncomment and edit the next two definitions,
@scheme[web-menu-name] and @scheme[web-address], to add an item to @racket[web-menu-name] and @racket[web-address], to add an item to
the @onscreen{Help} menu that opens a (course-specific) web page.} the @onscreen{Help} menu that opens a (course-specific) web page.}
@item{Replace @filepath{icon.png} in your renamed directory with a new @item{Replace @filepath{icon.png} in your renamed directory with a new

View File

@ -1,20 +1,19 @@
#lang scheme/base #lang racket/base
(require scheme/require) (require racket/require
scribble/manual
(require scribble/manual (for-label racket
(for-label scheme (subtract-in handin-server/checker racket)
(subtract-in handin-server/checker scheme) ;; racket/sandbox
;; scheme/sandbox
handin-server/sandbox handin-server/sandbox
handin-server/utils handin-server/utils
mred racket/gui/base
"hook-dummy.ss")) "hook-dummy.rkt"))
(provide (all-from-out scribble/manual) (provide (all-from-out scribble/manual)
(for-label (all-from-out scheme (for-label (all-from-out racket
handin-server/checker handin-server/checker
handin-server/sandbox handin-server/sandbox
handin-server/utils handin-server/utils
mred racket/gui/base
"hook-dummy.ss"))) "hook-dummy.rkt")))

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@;{John's comments: @;{John's comments:
- There's no enumerate? - There's no enumerate?

View File

@ -1,8 +1,6 @@
#lang scheme/base #lang racket/base
(provide hook) (provide hook)
(define (hook operation connection-context relevant-info) (define (hook operation connection-context relevant-info)
'bogus-value) 'bogus-value)

View File

@ -1,43 +1,43 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title[#:tag "multi-file"]{Multiple-File Submissions} @title[#:tag "multi-file"]{Multiple-File Submissions}
By default, the system is set up for submissions of single a single By default, the system is set up for submissions of single a single
file, straight fom DrRacket using the handin-client. There is some file, straight fom DrRacket using the handin-client. There is some
limited support for multi-file submissions in limited support for multi-file submissions in
@schememodname[handin-server/checker] and in the handin-client. It is @racketmodname[handin-server/checker] and in the handin-client. It is
possible to submit multiple files, and have the system generate a possible to submit multiple files, and have the system generate a
single file that is the concatenation of all submission files (used single file that is the concatenation of all submission files (used
only with text files). To set up multi-file submissions, do the only with text files). To set up multi-file submissions, do the
following: following:
@itemize[ @itemize[
@item{Add a @scheme[:multi-file] keyword in @scheme[check:], and as a @item{Add a @racket[:multi-file] keyword in @racket[check:], and as a
value, use the suffix that should be used for the single value, use the suffix that should be used for the single
concatenated output file.} concatenated output file.}
@item{You can also add a @scheme[:names-checker] keyword--the value @item{You can also add a @racket[:names-checker] keyword--the value
can be a regexp that all submitted files must follow (e.g., can be a regexp that all submitted files must follow (e.g.,
@scheme[".*[.]scm$"]), or a list of expected file names. @racket[".*[.]rkt$"]), or a list of expected file names.
Alternatively, it can be a 1-argument procedure that will receive Alternatively, it can be a 1-argument procedure that will receive
the (sorted) list of submitted files and can throw an error if some the (sorted) list of submitted files and can throw an error if some
files are missing or some files are forbidden.} files are missing or some files are forbidden.}
@item{Make sure that @scheme[:create-text?] is on if you want the @item{Make sure that @racket[:create-text?] is on if you want the
contents of a multi-file submission to be unpacked and filenames contents of a multi-file submission to be unpacked and filenames
checked.} checked.}
@item{In the @filepath{info.ss} file of the handin-client you need to @item{In the @filepath{info.rkt} file of the handin-client you need to
set @scheme[enable-multifile-handin] to @scheme[#t], and adjust set @racket[enable-multifile-handin] to @racket[#t], and adjust
@scheme[selection-default] to patterns that are common to your @racket[selection-default] to patterns that are common to your
course. (It can be a single pattern, or a list of them.)}] course. (It can be a single pattern, or a list of them.)}]
On the server side, each submission is saved in a file called On the server side, each submission is saved in a file called
@filepath{raw}, which contains all submitted files. In the @filepath{raw}, which contains all submitted files. In the
@filepath{grading} directory, you will get a @filepath{text.<sfx>} @filepath{grading} directory, you will get a @filepath{text.<sfx>}
file (@filepath{<sfx>} is the suffix that is used as a value for file (@filepath{<sfx>} is the suffix that is used as a value for
@scheme[:multi-file]) that contains all submitted files with clear @racket[:multi-file]) that contains all submitted files with clear
separators. A possible confusion is that every submission is a separators. A possible confusion is that every submission is a
complete set of files that overwrites any existing submission, whereas complete set of files that overwrites any existing submission, whereas
students may think that the server accumulates incoming files. To students may think that the server accumulates incoming files. To
@ -50,8 +50,8 @@ submission.
On the client side, students will have an additional file-menu entry On the client side, students will have an additional file-menu entry
for submitting multiple files, which pops up a dialog that can be used for submitting multiple files, which pops up a dialog that can be used
to submit multiple files. In this dialog, students choose their to submit multiple files. In this dialog, students choose their
working directory, and the @scheme[selection-default] entry from the working directory, and the @racket[selection-default] entry from the
@filepath{handin-client/info.ss} file specifies a few patterns that @filepath{handin-client/info.rkt} file specifies a few patterns that
can be used to automatically select files. The dialog provides all can be used to automatically select files. The dialog provides all
handin-related functionality that is available in DrRacket. For handin-related functionality that is available in DrRacket. For
further convenience, it can be used as a standalone application: in further convenience, it can be used as a standalone application: in

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Additional Utilities} @title{Additional Utilities}

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Quick Start for a Test Drive} @title{Quick Start for a Test Drive}
@ -19,22 +19,22 @@
NOTE: For real use, you need a new key.} NOTE: For real use, you need a new key.}
@item{Create a file @filepath{users.rktd} with the following content: @item{Create a file @filepath{users.rktd} with the following content:
@schemeblock[ @racketblock[
((tester ("8fe4c11451281c094a6578e6ddbf5eed" ((tester ("8fe4c11451281c094a6578e6ddbf5eed"
"Tester" "1" "test@cs")))]} "Tester" "1" "test@cs")))]}
@item{Make a @filepath{test} subdirectory in your new directory.} @item{Make a @filepath{test} subdirectory in your new directory.}
@item{Create a file @filepath{config.rktd} with the following content: @item{Create a file @filepath{config.rktd} with the following content:
@schemeblock[((active-dirs ("test")))]} @racketblock[((active-dirs ("test")))]}
@item{In your new directory, run @item{In your new directory, run
@commandline{gracket-text -l handin-server}} @commandline{gracket-text -l handin-server}}
@item{In the @filepath{handin-client} collection, edit @item{In the @filepath{handin-client} collection, edit
@filepath{info.ss} and uncomment the lines that define @filepath{info.rkt} and uncomment the lines that define
@scheme[server:port], @scheme[tools], @scheme[tool-names], and @racket[server:port], @racket[tools], @racket[tool-names], and
@scheme[tool-icons].} @racket[tool-icons].}
@item{Run @commandline{raco setup -l handin-client} @item{Run @commandline{raco setup -l handin-client}
@ -44,7 +44,7 @@
@item{Start DrRacket, click @onscreen{Handin} to run the client, @item{Start DrRacket, click @onscreen{Handin} to run the client,
submit with username ``@tt{tester}'' and password ``@tt{pw}''. submit with username ``@tt{tester}'' and password ``@tt{pw}''.
The submitted file will be @filepath{.../test/tester/handin.scm}.} The submitted file will be @filepath{.../test/tester/handin.rkt}.}
@item{Check the status of your submission by pointing a web browser at @item{Check the status of your submission by pointing a web browser at
@tt{https://localhost:7979/}. Note the ``s'' in ``@tt{https}''. Use @tt{https://localhost:7979/}. Note the ``s'' in ``@tt{https}''. Use

View File

@ -1,9 +1,9 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Sandbox} @title{Sandbox}
@defmodule[handin-server/sandbox] @defmodule[handin-server/sandbox]
This is just a wrapper around the sandbox engine from MzLib. It This is just a wrapper around the Racket sandbox engine. It
configures it for use with the handin server. configures it for use with the handin server.

View File

@ -1,11 +1,11 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Handin-Server and Client} @title{Handin-Server and Client}
The @filepath{handin-server} collection directory contains a server to be run by a The @filepath{handin-server} collection directory contains a server to
course instructor for accepting homework assignments and reporting on be run by a course instructor for accepting homework assignments and
submitted assignments. reporting on submitted assignments.
The @filepath{handin-client} collection directory contains a client to be The @filepath{handin-client} collection directory contains a client to be
customized then re-distributed to students in the course. The customized then re-distributed to students in the course. The

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title[#:tag "server-setup"]{Server Setup} @title[#:tag "server-setup"]{Server Setup}
@ -27,102 +27,102 @@ This directory contains the following files and sub-directories:
The following keys can be used: The following keys can be used:
@itemize[ @itemize[
@item{@indexed-scheme[active-dirs] --- a list of directories that @item{@indexed-racket[active-dirs] --- a list of directories that
are active submissions, relative to the current directory or are active submissions, relative to the current directory or
absolute; the last path element for each of these (and absolute; the last path element for each of these (and
@schemeid[inactive-dirs] below) should be unique, and is used to @racketid[inactive-dirs] below) should be unique, and is used to
identify the submission (for example, in the client's submission identify the submission (for example, in the client's submission
dialog and in the status servlet). If a specified directory does dialog and in the status servlet). If a specified directory does
not exist, it will be created.} not exist, it will be created.}
@item{@indexed-scheme[inactive-dirs] --- a list of inactive @item{@indexed-racket[inactive-dirs] --- a list of inactive
submission directories (see above for details).} submission directories (see above for details).}
@item{@indexed-scheme[port-number] --- the port for the main handin @item{@indexed-racket[port-number] --- the port for the main handin
server; the default is 7979.} server; the default is 7979.}
@item{@indexed-scheme[use-https] --- determines whether to start an @item{@indexed-racket[use-https] --- determines whether to start an
embedded web server for handin status reports; the default is embedded web server for handin status reports; the default is
@scheme[#t].} @racket[#t].}
@item{@indexed-scheme[session-timeout] --- number of seconds before @item{@indexed-racket[session-timeout] --- number of seconds before
the session times-out. The client is given this many seconds for the session times-out. The client is given this many seconds for
the login stage and then starts again so the same number of the login stage and then starts again so the same number of
seconds is given for the submit-validation process; the default is seconds is given for the submit-validation process; the default is
300.} 300.}
@item{@indexed-scheme[session-memory-limit] --- maximum size in @item{@indexed-racket[session-memory-limit] --- maximum size in
bytes of memory allowed for per-session computation, if bytes of memory allowed for per-session computation, if
per-session limits are supported (i.e., when using GRacket and per-session limits are supported (i.e., when using GRacket and
Racket with the (default) exact garbage collector and memory Racket with the (default) exact garbage collector and memory
accounting); the default is 40000000.} accounting); the default is 40000000.}
@item{@indexed-scheme[default-file-name] --- the default filename @item{@indexed-racket[default-file-name] --- the default filename
that will be saved with the submission contents. The default is that will be saved with the submission contents. The default is
@filepath{handin.scm}.} @filepath{handin.rkt}.}
@item{@indexed-scheme[max-upload] --- maximum size in bytes of an @item{@indexed-racket[max-upload] --- maximum size in bytes of an
acceptable submission; the default is 500000.} acceptable submission; the default is 500000.}
@item{@indexed-scheme[max-upload-keep] --- maximum index of @item{@indexed-racket[max-upload-keep] --- maximum index of
submissions to keep; the most recent submission is submissions to keep; the most recent submission is
@filepath{handin.scm} (by default), the next oldest is in @filepath{handin.rkt} (by default), the next oldest is in
@filepath{BACKUP-0/handin.scm}, next oldest is @filepath{BACKUP-0/handin.rkt}, next oldest is
@filepath{BACKUP-1/handin.scm}, etc. The default is 9.} @filepath{BACKUP-1/handin.rkt}, etc. The default is 9.}
@item{@indexed-scheme[user-regexp] --- a regular expression that is @item{@indexed-racket[user-regexp] --- a regular expression that is
used to validate usernames; alternatively, this can be @scheme[#f] used to validate usernames; alternatively, this can be @racket[#f]
meaning no restriction, or a list of permitted strings. Young meaning no restriction, or a list of permitted strings. Young
students often choose exotic usernames that are impossible to students often choose exotic usernames that are impossible to
remember, and forget capitalization, so the default is fairly remember, and forget capitalization, so the default is fairly
strict--- @scheme[#rx"^[a-z][a-z0-9]+$"]; a @litchar{+} is always strict--- @racket[#rx"^[a-z][a-z0-9]+$"]; a @litchar{+} is always
disallowed in a username, since it is used in a submission username disallowed in a username, since it is used in a submission username
to specify joint work.} to specify joint work.}
@item{@indexed-scheme[user-desc] --- a plain-words description of @item{@indexed-racket[user-desc] --- a plain-words description of
the acceptable username format (according to user-regexp above); the acceptable username format (according to user-regexp above);
@scheme[#f] stands for no description; the default is @racket[#f] stands for no description; the default is
@scheme["alphanumeric string"] which matches the default @racket["alphanumeric string"] which matches the default
user-regexp.} user-regexp.}
@item{@indexed-scheme[username-case-sensitive] --- a boolean; when @item{@indexed-racket[username-case-sensitive] --- a boolean; when
@scheme[#f], usernames are case-folded for all purposes; defaults @racket[#f], usernames are case-folded for all purposes; defaults
to @scheme[#f] (note that you should not set this to @scheme[#t] to @racket[#f] (note that you should not set this to @racket[#t]
on Windows or when using other case-insensitive filesystems, since on Windows or when using other case-insensitive filesystems, since
usernames are used as directory names).} usernames are used as directory names).}
@item{@indexed-scheme[allow-new-users] --- a boolean indicating @item{@indexed-racket[allow-new-users] --- a boolean indicating
whether to allow new-user requests from a client tool; the default whether to allow new-user requests from a client tool; the default
is @scheme[#f].} is @racket[#f].}
@item{@indexed-scheme[allow-change-info] --- a boolean indicating @item{@indexed-racket[allow-change-info] --- a boolean indicating
whether to allow changing user information from a client tool whether to allow changing user information from a client tool
(changing passwords is always possible); the default is (changing passwords is always possible); the default is
@scheme[#f].} @racket[#f].}
@item{@indexed-scheme[master-password] --- a string for an MD5 hash @item{@indexed-racket[master-password] --- a string for an MD5 hash
for a password that allows login as any user; the default is for a password that allows login as any user; the default is
@scheme[#f], which disables the password.} @racket[#f], which disables the password.}
@item{@indexed-scheme[log-output] --- a boolean that controls @item{@indexed-racket[log-output] --- a boolean that controls
whether the handin server log is written on the standard output; whether the handin server log is written on the standard output;
defaults to @scheme[#t].} defaults to @racket[#t].}
@item{@indexed-scheme[log-file] --- a path (relative to handin @item{@indexed-racket[log-file] --- a path (relative to handin
server directory or absolute) that specifies a filename for the server directory or absolute) that specifies a filename for the
handin server log (possibly combined with the @schemeid[log-output] handin server log (possibly combined with the @racketid[log-output]
option), or @scheme[#f] for no log file; defaults to option), or @racket[#f] for no log file; defaults to
@filepath{log}.} @filepath{log}.}
@item{@indexed-scheme[web-log-file] --- a path (relative to handin @item{@indexed-racket[web-log-file] --- a path (relative to handin
server directory or absolute) that specifies a filename for server directory or absolute) that specifies a filename for
logging the internal HTTPS status web server; or @scheme[#f] (the logging the internal HTTPS status web server; or @racket[#f] (the
default) to disable this log.} default) to disable this log.}
@item{@indexed-scheme[extra-fields] --- a list that describes extra @item{@indexed-racket[extra-fields] --- a list that describes extra
string fields of information for student records; each element in string fields of information for student records; each element in
this list is a list of three values: the name of the field, the this list is a list of three values: the name of the field, the
regexp (or @scheme[#f], or a list of permitted string values), and regexp (or @racket[#f], or a list of permitted string values), and
a string describing acceptable strings. The default is a string describing acceptable strings. The default is
@verbatim[#:indent 2]|{ @verbatim[#:indent 2]|{
(("Full Name" #f #f) (("Full Name" #f #f)
@ -148,7 +148,7 @@ This directory contains the following files and sub-directories:
@; JBC: a hyperlink here for users.rktd? @; JBC: a hyperlink here for users.rktd?
The second item in a field description can also be the symbol The second item in a field description can also be the symbol
@schemeid[-], which marks this field as one that is hidden from the @racketid[-], which marks this field as one that is hidden from the
user interface: students will not see it and will not be able to user interface: students will not see it and will not be able to
provide or modify it; when a new student creates an account, such provide or modify it; when a new student creates an account, such
fields will be left empty. This is useful for adding information fields will be left empty. This is useful for adding information
@ -157,11 +157,11 @@ This directory contains the following files and sub-directories:
@filepath{users.rktd} file and fill in such information. (The third @filepath{users.rktd} file and fill in such information. (The third
element for such descriptors is ignored.)} element for such descriptors is ignored.)}
@item{@indexed-scheme[hook-file] --- a path (relative to handin @item{@indexed-racket[hook-file] --- a path (relative to handin
server directory or absolute) that specifies a filename that server directory or absolute) that specifies a filename that
contains a `hook' module. This is useful as a general device for contains a `hook' module. This is useful as a general device for
customizing the server through Scheme code. The file is expected customizing the server through Racket code. The file is expected
to contain a module that provides a @scheme[hook] function, which to contain a module that provides a @racket[hook] function, which
should be receiving three arguments: should be receiving three arguments:
@defproc[(hook [operation symbol?] @defproc[(hook [operation symbol?]
@ -169,22 +169,22 @@ This directory contains the following files and sub-directories:
[relevant-info (listof (list/c symbol? any))]) [relevant-info (listof (list/c symbol? any))])
void?]{ void?]{
The @scheme[operation] argument indicates the operation that is The @racket[operation] argument indicates the operation that is
now taking place. It can be one of the following: now taking place. It can be one of the following:
@indexed-scheme['server-start], @indexed-scheme['server-connect], @indexed-racket['server-start], @indexed-racket['server-connect],
@indexed-scheme['user-create], @indexed-scheme['user-change], @indexed-racket['user-create], @indexed-racket['user-change],
@indexed-scheme['login], @indexed-scheme['submission-received], @indexed-racket['login], @indexed-racket['submission-received],
@indexed-scheme['submission-committed], @indexed-racket['submission-committed],
@indexed-scheme['submission-retrieved], @indexed-racket['submission-retrieved],
@indexed-scheme['status-login], or @indexed-racket['status-login], or
@indexed-scheme['status-file-get]. @indexed-racket['status-file-get].
The @scheme[connection-context] argument is a datum that specifies The @racket[connection-context] argument is a datum that specifies
the connection context (a number for handin connections, a the connection context (a number for handin connections, a
@schemeid[wN] symbol for servlet connections, and @scheme[#f] for @racketid[wN] symbol for servlet connections, and @racket[#f] for
other server operations). other server operations).
The @scheme[relevant-info] contains an alist of information The @racket[relevant-info] contains an alist of information
relevant to this operation. Currently, the hook is used in relevant to this operation. Currently, the hook is used in
several places after an operation has completed. several places after an operation has completed.
@ -192,8 +192,8 @@ This directory contains the following files and sub-directories:
notification messages when users are created or their notification messages when users are created or their
information has changed: information has changed:
@schememod[ @racketmod[
mzscheme racket/base
(provide hook) (provide hook)
(require net/sendmail) (require net/sendmail)
(define (hook what session alist) (define (hook what session alist)
@ -210,7 +210,7 @@ This directory contains the following files and sub-directories:
re-read, and options are reloaded. A few options are fixed at startup re-read, and options are reloaded. A few options are fixed at startup
time: port numbers and log file specs are fixed as configured at time: port numbers and log file specs are fixed as configured at
startup. All other options will change the behavior of the running startup. All other options will change the behavior of the running
server (but things like @schemeid[username-case-sensitive?] it would server (but things like @racketid[username-case-sensitive?] it would
be unwise to do so). (For safety, options are not reloaded until the be unwise to do so). (For safety, options are not reloaded until the
file parses correctly, but make sure that you don't save a copy that file parses correctly, but make sure that you don't save a copy that
has inconsistent options: it is best to create a new configuration has inconsistent options: it is best to create a new configuration
@ -221,25 +221,25 @@ This directory contains the following files and sub-directories:
@item{@filepath{users.rktd} (created if not present when a user is added): @item{@filepath{users.rktd} (created if not present when a user is added):
keeps the list of user accounts, along with the associated password keeps the list of user accounts, along with the associated password
(actually the MD5 hash of the password), and extra string fields as (actually the MD5 hash of the password), and extra string fields as
specified by the @schemeid[extra-fields] configuration entry (in the specified by the @racketid[extra-fields] configuration entry (in the
same order). The file format is same order). The file format is
@verbatim[#:indent 2]{ @verbatim[#:indent 2]{
((<username-sym> (<pw-md5-str> <extra-field> ...)) ((<username-sym> (<pw-md5-str> <extra-field> ...))
...)} ...)}
For example, the default @schemeid[extra-field] setting will make For example, the default @racketid[extra-field] setting will make
this: this:
@verbatim[#:indent 2]{ @verbatim[#:indent 2]{
((<username-sym> (<pw-md5-str> <full-name> <id> <email>)) ((<username-sym> (<pw-md5-str> <full-name> <id> <email>))
...)} ...)}
Usernames that begin with ``solution'' are special. They are used by Usernames that begin with ``solution'' are special. They are used by
the HTTPS status server. Independent of the @schemeid[user-regexp] the HTTPS status server. Independent of the @racketid[user-regexp]
and @schemeid[username-case-sensitive?] configuration items, usernames and @racketid[username-case-sensitive?] configuration items, usernames
are not allowed to contain characters that are illegal in Windows are not allowed to contain characters that are illegal in Windows
pathnames, and they cannot end or begin in spaces or periods. pathnames, and they cannot end or begin in spaces or periods.
If the @schemeid[allow-new-users] configuration allows new users, the If the @racketid[allow-new-users] configuration allows new users, the
@filepath{users.rktd} file can be updated by the server with new users. @filepath{users.rktd} file can be updated by the server with new users.
It can always be updated by the server to change passwords. It can always be updated by the server to change passwords.
@ -247,13 +247,13 @@ This directory contains the following files and sub-directories:
@filepath{/etc/passwd} or @filepath{/etc/shadow}), then you can @filepath{/etc/passwd} or @filepath{/etc/shadow}), then you can
construct a @filepath{users.rktd} file that will allow users to use construct a @filepath{users.rktd} file that will allow users to use
their normal passwords. To achieve this, use a list with their normal passwords. To achieve this, use a list with
@schemeid[unix] as the first element and the system's encrypted @racketid[unix] as the first element and the system's encrypted
password string as the second element. Such passwords can be used, password string as the second element. Such passwords can be used,
but when users change them, a plain md5 hash will be used. but when users change them, a plain md5 hash will be used.
You can combine this with other fields from the password file to You can combine this with other fields from the password file to
create your @filepath{users.rktd}, but make sure you have information create your @filepath{users.rktd}, but make sure you have information
that matches your @schemeid[extra-fields] specification. For example, that matches your @racketid[extra-fields] specification. For example,
given this system file: given this system file:
@verbatim[#:indent 2]|{ @verbatim[#:indent 2]|{
foo:wRzN1u5q2SqRD:1203:1203:L.E. Foo :/home/foo:/bin/tcsh foo:wRzN1u5q2SqRD:1203:1203:L.E. Foo :/home/foo:/bin/tcsh
@ -262,7 +262,7 @@ This directory contains the following files and sub-directories:
@verbatim[#:indent 2]|{ @verbatim[#:indent 2]|{
((foo ((unix "wRzN1u5q2SqRD") "L.E. Foo" "?")) ((foo ((unix "wRzN1u5q2SqRD") "L.E. Foo" "?"))
(bar ((unix "$1$dKlU0OkJ$t63TzKz") "Bar Z. Lie" "?")))}| (bar ((unix "$1$dKlU0OkJ$t63TzKz") "Bar Z. Lie" "?")))}|
which can be combined with this setting for @schemeid[extra-fields] in which can be combined with this setting for @racketid[extra-fields] in
your @filepath{config.rktd}: your @filepath{config.rktd}:
@verbatim[#:indent 2]{ @verbatim[#:indent 2]{
... ...
@ -274,15 +274,15 @@ This directory contains the following files and sub-directories:
their TA name. their TA name.
Finally, a password value can be a list that begins with a Finally, a password value can be a list that begins with a
@schemeid[plaintext] symbol, which will be used without encryption. @racketid[plaintext] symbol, which will be used without encryption.
This may be useful for manually resetting a forgotten passwords.} This may be useful for manually resetting a forgotten passwords.}
@item{@filepath{log} (or any other name that the @schemeid[log-file] @item{@filepath{log} (or any other name that the @racketid[log-file]
configuration option specifies (if any), created if not present, configuration option specifies (if any), created if not present,
appended otherwise): records connections and actions, where each entry appended otherwise): records connections and actions, where each entry
is of the form is of the form
@verbatim{[<id>|<time>] <msg>} @verbatim{[<id>|<time>] <msg>}
where @schemeid[<id>] is an integer representing the connection where @racketid[<id>] is an integer representing the connection
(numbered consecutively from 1 when the server starts), ``@tt{-}'' for (numbered consecutively from 1 when the server starts), ``@tt{-}'' for
a message without a connection, and ``@tt{wN}'' for a message from the a message without a connection, and ``@tt{wN}'' for a message from the
status servlet.} status servlet.}
@ -290,11 +290,11 @@ This directory contains the following files and sub-directories:
@item{Active and inactive assignment directories (which you can put in @item{Active and inactive assignment directories (which you can put in
a nested directory for convenience, or specify a different absolute a nested directory for convenience, or specify a different absolute
directory), as specified by the configuration file using the directory), as specified by the configuration file using the
@schemeid[active-dirs] and @schemeid[inactive-dirs]. A list of active @racketid[active-dirs] and @racketid[inactive-dirs]. A list of active
assignment directories (the last path element in each specified path assignment directories (the last path element in each specified path
is used as a label) is sent to the client tool when a student clicks is used as a label) is sent to the client tool when a student clicks
@onscreen{Handin}. The assignment labels are ordered in the student's @onscreen{Handin}. The assignment labels are ordered in the student's
menu using @scheme[string<?], and the first assignment is the default menu using @racket[string<?], and the first assignment is the default
selection. selection.
Within each assignment directory, the student id is used for a Within each assignment directory, the student id is used for a
@ -317,20 +317,20 @@ This directory contains the following files and sub-directories:
might not finish. When the server is started, it automatically runs might not finish. When the server is started, it automatically runs
the cleanup process for each student directory. the cleanup process for each student directory.
Within a student directory, a @filepath{handin.scm} file (or some Within a student directory, a @filepath{handin.rkt} file (or some
other name if the @schemeid[default-file-name] option is set) contains other name if the @racketid[default-file-name] option is set) contains
the actual submission. A @scheme[checker] procedure can change this the actual submission. A @racket[checker] procedure can change this
default file name, and it can create additional files in an default file name, and it can create additional files in an
@filepath{ATTEMPT} directory (to be copied by the cleanup process); @filepath{ATTEMPT} directory (to be copied by the cleanup process);
see below for more details on @schememodname[handin-server/checker]. see below for more details on @racketmodname[handin-server/checker].
For submissions from a normal DrRacket frame, a submission file For submissions from a normal DrRacket frame, a submission file
contains a copy of the student's definitions and interactions contains a copy of the student's definitions and interactions
windows. The file is in a binary format (to support non-text code), windows. The file is in a binary format (to support non-text code),
and opening the file directly in DrRacket shows the definitions and opening the file directly in DrRacket shows the definitions
part. To get both the definitions and interactions parts, the file part. To get both the definitions and interactions parts, the file
can be parsed with @scheme[unpack-submission] from can be parsed with @racket[unpack-submission] from
@schememodname[handin-server/utils]. @racketmodname[handin-server/utils].
To submit an assignment as a group, students use a concatenation of To submit an assignment as a group, students use a concatenation of
usernames separated by ``@tt{+}'' and any number of spaces (e.g., usernames separated by ``@tt{+}'' and any number of spaces (e.g.,
@ -343,19 +343,19 @@ This directory contains the following files and sub-directories:
Inactive assignment directories are used by the HTTPS status web Inactive assignment directories are used by the HTTPS status web
server.} server.}
@item{@filepath{<active-assignment>/checker.ss} (optional): a module @item{@filepath{<active-assignment>/checker.rkt} (optional): a module
that exports a @scheme[checker] function. This function receives that exports a @racket[checker] function. This function receives
two two
@; JBC: use defproc here? @; JBC: use defproc here?
arguments: a username list and a submission as a byte string. (See arguments: a username list and a submission as a byte string. (See
also @scheme[unpack-submission], etc. from also @racket[unpack-submission], etc. from
@schememodname[handin-server/utils].) To @racketmodname[handin-server/utils].) To
reject the submission, the @scheme[checker] function can raise an reject the submission, the @racket[checker] function can raise an
exception; the exception message will be relayed back to the exception; the exception message will be relayed back to the
student. The module is loaded when the current directory is the student. The module is loaded when the current directory is the
main server directory, so it can read files from there (but note main server directory, so it can read files from there (but note
that to read values from @filepath{config.rktd} it is better to use that to read values from @filepath{config.rktd} it is better to use
@scheme[get-conf]). Also, the module will be reloaded if the @racket[get-conf]). Also, the module will be reloaded if the
checker file is modified; there's no need to restart the server, checker file is modified; there's no need to restart the server,
but make sure that you do not save a broken checker (i.e., do not but make sure that you do not save a broken checker (i.e., do not
save in mid-edit). save in mid-edit).
@ -365,10 +365,10 @@ This directory contains the following files and sub-directories:
the submission username was a concatenation of usernames separated the submission username was a concatenation of usernames separated
by ``@tt{+}''). by ``@tt{+}'').
The @scheme[checker] function is called with the current directory The @racket[checker] function is called with the current directory
as @filepath{<active-assignment>/<username(s)>/ATTEMPT}, and the as @filepath{<active-assignment>/<username(s)>/ATTEMPT}, and the
submission is saved in the file @filepath{handin}, and the timeout submission is saved in the file @filepath{handin}, and the timeout
clock is reset to the value of the @scheme[session-timeout] clock is reset to the value of the @racket[session-timeout]
configuration. The checker function can change @filepath{handin}, configuration. The checker function can change @filepath{handin},
and it can create additional files in this directory. (Extra and it can create additional files in this directory. (Extra
files in the current directory will be preserved as it is later files in the current directory will be preserved as it is later
@ -378,12 +378,12 @@ This directory contains the following files and sub-directories:
put the files in a subdirectory, it is preserved but hidden from put the files in a subdirectory, it is preserved but hidden from
the status interface. the status interface.
The checker should return a string, such as @filepath{handin.scm}, The checker should return a string, such as @filepath{handin.rkt},
to use in naming the submission file, or @scheme[#f] to indicate to use in naming the submission file, or @racket[#f] to indicate
that he file should be deleted (e.g., when the checker alrady that he file should be deleted (e.g., when the checker alrady
created the submission file(s) in a different place). created the submission file(s) in a different place).
Alternatively, the module can bind @scheme[checker] to a list of Alternatively, the module can bind @racket[checker] to a list of
three procedures: a pre-checker, a checker, and a post-checker. three procedures: a pre-checker, a checker, and a post-checker.
All three are applied in exactly the same way as the checker (same All three are applied in exactly the same way as the checker (same
arguments, and always within the submission directory), except arguments, and always within the submission directory), except
@ -394,7 +394,7 @@ This directory contains the following files and sub-directories:
submission directory does not have a @filepath{SUCCESS-*} submission directory does not have a @filepath{SUCCESS-*}
directory, then the whole submission directory is removed. This directory, then the whole submission directory is removed. This
is useful for checking that the user/s are valid; if you allow a is useful for checking that the user/s are valid; if you allow a
submission only when @scheme[users] is @scheme['("foo" "bar")], submission only when @racket[users] is @racket['("foo" "bar")],
and ``@tt{foo}'' tries to submit alone, then the submission and ``@tt{foo}'' tries to submit alone, then the submission
directory for ``@tt{foo}'' should be removed to allow a proper directory for ``@tt{foo}'' should be removed to allow a proper
submission later. Note that the timeout clock is reset only submission later. Note that the timeout clock is reset only
@ -406,17 +406,17 @@ This directory contains the following files and sub-directories:
considered successful, so this function should avoid throwing an considered successful, so this function should avoid throwing an
exception (it can, but the submission will still be in place). exception (it can, but the submission will still be in place).
This is useful for things like notifying the user of the This is useful for things like notifying the user of the
successful submission (see @scheme[message]), or sending a successful submission (see @racket[message]), or sending a
``receipt'' email.}] ``receipt'' email.}]
To specify only pre/post-checker, use @scheme[#f] for the one you To specify only pre/post-checker, use @racket[#f] for the one you
want to omit.} want to omit.}
@item{@filepath{<[in]active-assignment>/<user(s)>/<filename>} (if @item{@filepath{<[in]active-assignment>/<user(s)>/<filename>} (if
submitted): the most recent submission for submitted): the most recent submission for
@tt{<[in]active-assignment>} by @tt{<user(s)>} where <filename> was @tt{<[in]active-assignment>} by @tt{<user(s)>} where <filename> was
returned by the checker (or the value of the returned by the checker (or the value of the
@schemeid[default-file-name] configuration option if there's no @racketid[default-file-name] configuration option if there's no
checker). If the submission is from multiple users, then checker). If the submission is from multiple users, then
``@tt{<user(s)>}'' is actually ``@tt{<user1>+<user2>}'' etc. Also, if ``@tt{<user(s)>}'' is actually ``@tt{<user1>+<user2>}'' etc. Also, if
the cleanup process was interrupted (by a machine failure, etc.), the the cleanup process was interrupted (by a machine failure, etc.), the
@ -438,8 +438,8 @@ This directory contains the following files and sub-directories:
] ]
The server can be run within either Racket or GRacket, but The server can be run within either Racket or GRacket, but
@schememodname[handin-server/utils] requires GRacket (which means that @racketmodname[handin-server/utils] requires GRacket (which means that
@scheme[checker] modules will likely require the server to run under @racket[checker] modules will likely require the server to run under
GRacket). Remember that if you're not using the (default) 3m garbage GRacket). Remember that if you're not using the (default) 3m garbage
collector you don't get memory accounting. collector you don't get memory accounting.
@ -471,7 +471,7 @@ the correct assignment in the handin dialog.
A student can download his/her own submissions through the handin A student can download his/her own submissions through the handin
dialog. This can also be done through a web server that runs dialog. This can also be done through a web server that runs
concurrently with the handin server (on the same port) if you set the concurrently with the handin server (on the same port) if you set the
@scheme[use-https] option in the configuration file to @scheme[#t] (the @racket[use-https] option in the configuration file to @racket[#t] (the
default). The starting URL is default). The starting URL is
@commandline{https://SERVER:PORT/} @commandline{https://SERVER:PORT/}

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Auto-Updater} @title{Auto-Updater}
@ -9,20 +9,20 @@ additional functionality (collections, teachpacks, language-levels
etc), and this functionality can change (or expected to change, for etc), and this functionality can change (or expected to change, for
example, distributing per-homework teachpacks). example, distributing per-homework teachpacks).
To enable this, uncomment the relevant part of the @filepath{info.ss} To enable this, uncomment the relevant part of the @filepath{info.rkt}
file in the client code. It has the following three keys: file in the client code. It has the following three keys:
@indexed-scheme[enable-auto-update] that turns this facility on, and @indexed-racket[enable-auto-update] that turns this facility on, and
@indexed-scheme[version-filename] and @indexed-racket[version-filename] and
@indexed-scheme[package-filename] which are the expected file names of @indexed-racket[package-filename] which are the expected file names of
the version file and the @filepath{.plt} file relative to the course the version file and the @filepath{.plt} file relative to the course
web address (the value of the @scheme[web-address] key). Also, web address (the value of the @racket[web-address] key). Also,
include in your client collection a @filepath{version} file that include in your client collection a @filepath{version} file that
contains a single number that is its version. Use a big integer that contains a single number that is its version. Use a big integer that
holds the time of this collection in a @tt{YYYYMMDDHHMM} format. holds the time of this collection in a @tt{YYYYMMDDHHMM} format.
When students install the client, every time DrRacket starts, it will When students install the client, every time DrRacket starts, it will
automatically check the version from the web page (as specified by the automatically check the version from the web page (as specified by the
@scheme[web-address] and @scheme[version-filename] keys), and if that @racket[web-address] and @racket[version-filename] keys), and if that
contains a bigger number, it will offer the students to download and contains a bigger number, it will offer the students to download and
install the new version. So, every time you want to distribute a new install the new version. So, every time you want to distribute a new
version, you build a new @filepath{.plt} file that contains a new version, you build a new @filepath{.plt} file that contains a new

View File

@ -1,5 +1,5 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title{Utilities} @title{Utilities}
@ -15,7 +15,7 @@
@defproc[(unpack-submission [submission bytes?]) @defproc[(unpack-submission [submission bytes?])
(values (is-a?/c text%) (is-a?/c text%))]{ (values (is-a?/c text%) (is-a?/c text%))]{
Returns two @scheme[text%] objects corresponding to the submitted Returns two @racket[text%] objects corresponding to the submitted
definitions and interactions windows.} definitions and interactions windows.}
@defproc[(make-evaluator/submission @defproc[(make-evaluator/submission
@ -27,18 +27,18 @@
[content bytes?]) [content bytes?])
(any/c . -> . any)]{ (any/c . -> . any)]{
Like @scheme[make-evaluator], but the definitions content is Like @racket[make-evaluator], but the definitions content is
supplied as a submission byte string. The byte string is opened for supplied as a submission byte string. The byte string is opened for
reading, with line-counting enabled. reading, with line-counting enabled.
In addition to the language specification for In addition to the language specification for
@scheme[make-evaluator], the @scheme[language] argument can be a @racket[make-evaluator], the @racket[language] argument can be a
list that begins with @scheme['module]. In this case, list that begins with @racket['module]. In this case,
@scheme[make-module-language] is used to create an evaluator, and @racket[make-module-language] is used to create an evaluator, and
the module code must be using the specified language in its the module code must be using the specified language in its
language position. In this case, the @scheme[requires-paths] language position. In this case, the @racket[requires-paths]
argument is used only for paths that are allowed to be accessed (the argument is used only for paths that are allowed to be accessed (the
@scheme[_allow-read] argument to @scheme[make-evaluator], since the @racket[_allow-read] argument to @racket[make-evaluator], since the
submission is expected to be a complete submission.)} submission is expected to be a complete submission.)}
@defproc[(call-with-evaluator @defproc[(call-with-evaluator
@ -51,14 +51,14 @@
[proc (any/c . -> . any)]) [proc (any/c . -> . any)])
any]{ any]{
Calls @scheme[proc] with an evaluator for the given language, Calls @racket[proc] with an evaluator for the given language,
teachpack paths, and initial definition content as supplied by teachpack paths, and initial definition content as supplied by
@scheme[input-program] (see @scheme[make-evaluator]). It also sets @racket[input-program] (see @racket[make-evaluator]). It also sets
the current error-value print handler to print values in a way the current error-value print handler to print values in a way
suitable for @scheme[language], it initializes suitable for @racket[language], it initializes
@scheme[set-run-status] with @scheme["executing your code"], and it @racket[set-run-status] with @racket["executing your code"], and it
catches all exceptions to re-raise them in a form suitable as a catches all exceptions to re-raise them in a form suitable as a
submission error. See @scheme[make-evaluator/submission] for submission error. See @racket[make-evaluator/submission] for
further details.} further details.}
@defproc[(call-with-evaluator/submission @defproc[(call-with-evaluator/submission
@ -71,23 +71,23 @@
[proc (any/c . -> . any)]) [proc (any/c . -> . any)])
any]{ any]{
Like @scheme[call-with-evaluator], but the definitions content is Like @racket[call-with-evaluator], but the definitions content is
supplied as a byte string. The byte string is opened for reading, supplied as a byte string. The byte string is opened for reading,
with line-counting enabled. See @scheme[call-with-evaluator] and with line-counting enabled. See @racket[call-with-evaluator] and
@scheme[make-evaluator/submission] for further details.} @racket[make-evaluator/submission] for further details.}
@; JBC: this contract is probably wrong @; JBC: this contract is probably wrong
@; JBC: does this eval accept an optional namespace? @; JBC: does this eval accept an optional namespace?
@defproc[(evaluate-all [source any] @defproc[(evaluate-all [source any]
[input-port port?] [input-port port?]
[eval (any/c . -> . any)]) any]{ [eval (any/c . -> . any)]) any]{
Like @scheme[load] on an input port.} Like @racket[load] on an input port.}
@defproc[(evaluate-submission [submission bytes?] @defproc[(evaluate-submission [submission bytes?]
[eval (any/c . -> . any)]) [eval (any/c . -> . any)])
any]{ any]{
Like @scheme[load] on a submission byte string.} Like @racket[load] on a submission byte string.}
@defproc[(check-proc [eval (any/c . -> . any)] @defproc[(check-proc [eval (any/c . -> . any)]
[expect-v any/c] [expect-v any/c]
@ -96,21 +96,21 @@
[arg any/c] ...) [arg any/c] ...)
any]{ any]{
Calls the function named @scheme[proc-name] using the evaluator Calls the function named @racket[proc-name] using the evaluator
@scheme[eval], giving it the (unquoted) arguments @scheme[arg ...] @racket[eval], giving it the (unquoted) arguments @racket[arg ...]
Let @scheme[result-v] be the result of the call; unless Let @racket[result-v] be the result of the call; unless
@scheme[(compare-proc result-v expect-v)] is true, an exception is @racket[(compare-proc result-v expect-v)] is true, an exception is
raised.} raised.}
Every exception or result mismatch during the call to Every exception or result mismatch during the call to
@scheme[compare-proc] is phrased suitably for the handin client. @racket[compare-proc] is phrased suitably for the handin client.
@defproc[(check-defined [eval (any/c . -> . any)] @defproc[(check-defined [eval (any/c . -> . any)]
[name symbol?]) [name symbol?])
any]{ any]{
Checks whether @scheme[name] is defined in the evaluator Checks whether @racket[name] is defined in the evaluator
@scheme[eval], and raises an error if not (suitably phrased for the @racket[eval], and raises an error if not (suitably phrased for the
handin client). If it is defined as non-syntax, its value is handin client). If it is defined as non-syntax, its value is
returned. Warning: in the beginner language level, procedure returned. Warning: in the beginner language level, procedure
definitions are bound as syntax.} definitions are bound as syntax.}
@ -120,8 +120,8 @@ Every exception or result mismatch during the call to
@defproc[(look-for-tests [text (is-a?/c text%)] [name symbol?] [n number?]) @defproc[(look-for-tests [text (is-a?/c text%)] [name symbol?] [n number?])
any]{ any]{
Inspects the given @scheme[text%] object to determine whether it Inspects the given @racket[text%] object to determine whether it
contains at least @scheme[n] tests for the function @scheme[name]. contains at least @racket[n] tests for the function @racket[name].
The tests must be top-level expressions.} The tests must be top-level expressions.}
@defproc[(user-construct [eval (any/c . -> . any)] @defproc[(user-construct [eval (any/c . -> . any)]
@ -129,7 +129,7 @@ Every exception or result mismatch during the call to
[arg any/c] ...) [arg any/c] ...)
any]{ any]{
Like @scheme[check-proc], but with no result checking. This Like @racket[check-proc], but with no result checking. This
function is often useful for calling a student-defined constructor.} function is often useful for calling a student-defined constructor.}
@defparam[test-history-enabled on? any/c]{ @defparam[test-history-enabled on? any/c]{
@ -145,22 +145,22 @@ Every exception or result mismatch during the call to
[styles (listof (or/c 'ok 'ok-cancel 'yes-no [styles (listof (or/c 'ok 'ok-cancel 'yes-no
'caution 'stop))]) 'caution 'stop))])
any])]{ any])]{
The first case of @scheme[message] is intended to update the client on The first case of @racket[message] is intended to update the client on
the current activity --- it updates the status line in the submission the current activity --- it updates the status line in the submission
dialog box on the client. Use it to indicate operations that might dialog box on the client. Use it to indicate operations that might
take a while and/or indicate progress during these operations. take a while and/or indicate progress during these operations.
In the second case, where @scheme['final] is used as a flag, does not In the second case, where @racket['final] is used as a flag, does not
show the text immediately --- instead, it causes it to be displayed in show the text immediately --- instead, it causes it to be displayed in
the status line after a successful submission instead of the usual the status line after a successful submission instead of the usual
``Handin successful'' message. This is useful for submissions that ``Handin successful'' message. This is useful for submissions that
are accepted but had some problems. are accepted but had some problems.
The third case, when @scheme[styles] is a list of symbols, opens a The third case, when @racket[styles] is a list of symbols, opens a
@scheme[message-box] dialog on the client side, and the resulting @racket[message-box] dialog on the client side, and the resulting
value is returned as the result of @scheme[message]. The value is returned as the result of @racket[message]. The
@scheme[styles] list is passed as the @scheme[style] argument to @racket[styles] list is passed as the @racket[style] argument to
@scheme[message-box]. You can use this to send warnings to the @racket[message-box]. You can use this to send warnings to the
student or to ask for confirmation, for example, ``your submission student or to ask for confirmation, for example, ``your submission
does not pass 3 tests, continue?''.} does not pass 3 tests, continue?''.}
@ -172,16 +172,16 @@ Every exception or result mismatch during the call to
session aborted.} session aborted.}
@defparam[current-value-printer proc (any/c . -> . string?)]{ @defparam[current-value-printer proc (any/c . -> . string?)]{
Controls how values are printed. The @scheme[proc] must be a Controls how values are printed. The @racket[proc] must be a
procedure that expects a Scheme value and returns a string procedure that expects a Racket value and returns a string
representation for it. The default value printer uses representation for it. The default value printer uses
@scheme[pretty-print], with DrRacket-like settings.} @racket[pretty-print], with DrRacket-like settings.}
@defproc[(reraise-exn-as-submission-problem [thunk (-> any)]) any]{ @defproc[(reraise-exn-as-submission-problem [thunk (-> any)]) any]{
Calls @scheme[thunk] in a context that catches exceptions and Calls @racket[thunk] in a context that catches exceptions and
re-raises them in a form suitable as a submission error. It returns re-raises them in a form suitable as a submission error. It returns
the value returned by @scheme[thunk] if no exception occurs.} the value returned by @racket[thunk] if no exception occurs.}
@defproc[(log-line [fmt string?] [args any/c] ...) void?]{ @defproc[(log-line [fmt string?] [args any/c] ...) void?]{
Produces a line in the server log file, using the given format Produces a line in the server log file, using the given format
@ -193,14 +193,14 @@ Every exception or result mismatch during the call to
@defproc[(timeout-control [msg string?]) void?]{ @defproc[(timeout-control [msg string?]) void?]{
Controls the timeout for this session. The timeout is initialized Controls the timeout for this session. The timeout is initialized
by the value of the @scheme[session-timeout] configuration entry, by the value of the @racket[session-timeout] configuration entry,
and the checker can use this procedure to further control it: if and the checker can use this procedure to further control it: if
@scheme[msg] is @scheme['reset] the timeout is reset to @racket[msg] is @racket['reset] the timeout is reset to
@scheme[session-timeout] seconds; if @scheme[msg] is a number the @racket[session-timeout] seconds; if @racket[msg] is a number the
timeout will be set to that many seconds in the future. The timeout timeout will be set to that many seconds in the future. The timeout
can be completely disabled by @scheme[(timeout-control #f)]. (Note can be completely disabled by @racket[(timeout-control #f)]. (Note
that before the checker is used (after the pre-checker, if that before the checker is used (after the pre-checker, if
specified), the timer will be reset to the @scheme['session-timeout] specified), the timer will be reset to the @racket['session-timeout]
value.)} value.)}
@defthing[server-dir path-string?]{ @defthing[server-dir path-string?]{

View File

@ -1,11 +1,11 @@
#lang scribble/doc #lang scribble/doc
@(require "common.ss") @(require "common.rkt")
@title[#:tag "wheres-the-collection"]{Where is the Collection?} @title[#:tag "wheres-the-collection"]{Where is the Collection?}
If you obtained the server and client by installing a @filepath{.plt} If you obtained the server and client by installing a @filepath{.plt}
file, then the @filepath{handin-server} and @filepath{handin-client} file, then the @filepath{handin-server} and @filepath{handin-client}
directories might be in your Racket addon space. Start Racket, and directories might be in your Racket addon space. Start Racket, and
enter @schemeblock[(collection-path "handin-server")] enter @racketblock[(collection-path "handin-server")]
@schemeblock[(collection-path "handin-client")] to find out where @racketblock[(collection-path "handin-client")] to find out where
these collections are. these collections are.

View File

@ -1,14 +1,14 @@
#lang scheme/base #lang racket/base
(require scheme/class mred scheme/pretty (require racket/class racket/gui/base racket/pretty
(prefix-in pc: mzlib/pconvert) (prefix-in pc: mzlib/pconvert)
(only-in "main.ss" timeout-control) (only-in "main.rkt" timeout-control)
"private/run-status.ss" "private/run-status.rkt"
"private/config.ss" "private/config.rkt"
"private/logger.ss" "private/logger.rkt"
"sandbox.ss") "sandbox.rkt")
(provide (all-from-out "sandbox.ss") (provide (all-from-out "sandbox.rkt")
get-conf get-conf
log-line log-line

View File

@ -1,16 +1,16 @@
#lang scheme/base #lang racket/base
(require scheme/list (require racket/list
scheme/path racket/path
scheme/file racket/file
scheme/date racket/date
net/uri-codec net/uri-codec
web-server/servlet web-server/servlet
handin-server/private/md5 handin-server/private/md5
handin-server/private/logger handin-server/private/logger
handin-server/private/config handin-server/private/config
handin-server/private/hooker handin-server/private/hooker
"run-servlet.ss") "run-servlet.rkt")
(define (aget alist key) (define (aget alist key)
(cond [(assq key alist) => cdr] [else #f])) (cond [(assq key alist) => cdr] [else #f]))
@ -182,7 +182,8 @@
(let* ([data (file->bytes file)] (let* ([data (file->bytes file)]
[html? (regexp-match? #rx"[.]html?$" (string-foldcase tag))] [html? (regexp-match? #rx"[.]html?$" (string-foldcase tag))]
[wxme? (regexp-match? [wxme? (regexp-match?
#rx#"^(?:#reader[(]lib\"read.ss\"\"wxme\"[)])?WXME" data)]) #rx#"^(?:#reader[(]lib\"read.(?:ss|rkt)\"\"wxme\"[)])?WXME"
data)])
(make-response/full 200 #"Okay" (current-seconds) (make-response/full 200 #"Okay" (current-seconds)
(cond [html? #"text/html"] (cond [html? #"text/html"]
[wxme? #"application/data"] [wxme? #"application/data"]