############################################################################
#
# File: webup.icn
#
# Subject: A rudimentary web-based updater/patcher.
#
# Author: Clint Jeffery
#
# Date: 30 June 2010
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# webupdate(URL, title) pulls down files from URL to replace local files
# with different file sizes or older modified time stamps.
#
# Web site structure is at present: three subdirectories
# ("linux","windows","shared"), each of which has a MANIFEST directory
# containing a list of files; each line of the MANIFEST is of the form
#
# filename filesize timestamp
#
# MANIFEST may also contain blank and commented-out lines beginning with #
#
# At present this is a GUI module that opens its own dialog.
# It is desirable that the updating be separated from the GUI part.
#
############################################################################
#
# Links: gui
#
############################################################################
global webupsite, webuptitle
procedure webupdate(website: string, title: "web update")
local d
webupsite := website
webuptitle := title
d := dialogtable()
d.show_modal()
end
class dialogtable()
method show_modal()
local d, L, platform, dir, N
d := UnicronProgressBar()
d.show_modeless()
platform :=
$ifdef _UNIX
"linux"
$else
"windows"
$endif
N := 0
every dir := (platform | "shared") do {
d.syncdir := dir
if *(L := d.check()) > 0 then {
N +:= *L
handle_updates(L, d)
}
}
if N = 0 then {
d.message("no files updated")
delay(500)
d.dispose()
}
else {
d.message((N/3) || " files updated")
delay(3500)
d.dispose()
}
end
method handle_updates(L, d)
local fn, reason, size, errs, nerrs
errs := ""
nerrs := 0
while fn := pop(L) do {
reason := pop(L)
size := pop(L)
errs ||:= d.update(fn, reason, size) || " "
}
if errs ~== "" then {
d.message("exiting because: " || errs)
dispatcher.message_loop(d)
exit(-1)
}
d.message("updated " || fn || ", continuing")
delay(800)
return
end
end
$include "guiconst.icn"
class ProgressBar : Component (
p,
bar_x, bar_y, bar_w, bar_h
)
method resize()
/h_spec := WAttrib(cwin, "fheight") + 2 * DEFAULT_TEXT_Y_SURROUND
self$Component.resize()
bar_x := x + DEFAULT_TEXT_X_SURROUND
bar_y := y + BORDER_WIDTH + 3
bar_w := w - 2 * DEFAULT_TEXT_X_SURROUND
bar_h := h - 2 * (BORDER_WIDTH + 3)
end
method display(buffer_flag)
local cw
EraseRectangle(cbwin,x,y,w,h)
DrawRaisedRectangle(cbwin, x, y, w, h)
FillRectangle(cbwin, bar_x, bar_y, bar_w * p / 100.0, bar_h)
cw := Clone(cbwin, "drawop=reverse")
center_string(cw, x + w/2, y + h/2, p || "%")
Uncouple(cw)
if /buffer_flag then CopyArea(cbwin, cwin, x, y, w, h, x, y)
return
end
method handle_event(e)
if integer(e) = (&lpress|&rpress|&mpress) &
in_region() & (&x <= bar_x + bar_w) then {
set_percentage((100 * (&x - bar_x)) / bar_w)
return _Event(e, self, 0)
}
end
method get_percentage()
return p
end
method set_percentage(pct)
p := pct
redisplay()
end
initially(argv[])
self$Component.initially()
set_percentage(0)
if *argv > 0 then set_fields(argv)
end
class UnicronProgressBar : _Dialog(lab, fnlab, pb, closebtn, syncdir)
method dialog_event(ev)
case ev.get_component() of {
pb :
write("pb produced an event - percentage = ", pb.get_percentage())
closebtn: {
if ev.get_code() > 0 then {
dispose()
win := &null
}
}
}
end
method message(s)
lab.set_label(s)
if \ (is_open) then {
lab.resize()
display()
}
end
method check()
local platform, url, db, filen, size, mtime, L, r, fs
url := distfile("MANIFEST")
message("checking "|| url|| "...")
db := open(url, "m") | {
write("can't update, was trying to read ", image(url))
fail
}
message("checking... opened " || url)
L := []
while r := read(db) do {
if (r == "") | (r[1] == "#") | match("filename ",r) then next
r ? {
filen := tab(upto(' \t'))|write("no filename in ", image(r))
tab(many(' \t'))
size := numeric(tab(many(&digits)))|
write("no filesize in ", image(r))
tab(many(' \t'))
mtime := numeric(tab(many(&digits)))|
write("no mtime in ", image(r))
}
message("checking " || filen)
if not (fs := stat(filen)) then {
put(L, filen, "because it is a new file", size)
}
else if fs.size ~= size then {
put(L, filen, "because its size ("||size||
") is different than ours (" || fs.size||")", size)
}
else if fs.mtime < mtime then {
put(L, filen, "because it is newer ("||mtime||
") than ours (" || fs.mtime || ")", size)
}
else {
#write("don't think we updated ", filen)
#write("\tbecause ", image(fs.size), " = ", image(size))
#write("\tbecause ", image(fs.mtime), " >= ", image(mtime))
}
}
close(db)
return L
end
method distfile(fn)
return "http://" || webupsite || syncdir || "/" || fn
end
method update(fn, reason, size)
local fetcher, s, fo, newfile, percent, total
if /win then stop("can't update ", fn, " win is gone")
message("updating " || fn || " " || reason)
WAttrib(win, "pointer=" || ("wait"|"watch"))
fnlab.set_label(fn)
pb.set_percentage(0)
(fetcher := open(distfile(fn), "m")) | {
s := "can't get contents of " || fn
message(s)
WAttrib(win, "pointer=arrow")
return s
}
message("httpget (" || image(fetcher) || ")")
if not (fo := datopen(fn, "wu")) then {
fn := "new-" || fn
if not (fo := datopen(fn, "wu")) then {
s := "can't open "||fn||" for writing"
message(s)
WAttrib(win, "pointer=arrow")
return s
}
}
total := 0
while writes(fo, s := reads(fetcher, 1024)) do {
total +:= *s
percent := 100 * total / size
if percent > 100 then percent := 100
pb.set_percentage(percent)
}
close(fo)
if match("new-", fn) then {
s := "couldn't write " || fn[4:0] ||
"; close ALL programs and rerun unicron to patch"
message(s)
newfile := datopen("new-files","a")
write(newfile, fn)
close(newfile)
WAttrib(win, "pointer=arrow")
return s
}
else
message("updated " || fn)
WAttrib(win, "pointer=arrow")
end
initially
local t
self$_Dialog.initially()
set_attribs("label=" || webuptitle, "size=644,399",
"font=sans", "bg=yellowish white", "resize=on")
t := Label("pos=10%,15%", "size=80%,10%",
"internal_alignment=c",
"label=Checking for update files! please wait...")
t.set_attribs("font=serif,28,bold","fg=blue")
add(t)
lab := Label("pos=50%,80%", "size=90%,10%", "align=c,c",
"label=initializing...")
lab.set_attribs("font=serif,18,bold")
add(lab)
fnlab := Label("pos=50%,38%", "size=50%,15%", "align=c,c",
"label=no files updated")
fnlab.set_attribs("font=serif,18,bold")
add(fnlab)
pb := ProgressBar("pos=50%,50%", "size=50%", "align=c,c")
add(pb)
closebtn := TextButton("label=Close", "pos=50%,66%", "align=c,c")
add(closebtn)
set_focus(closebtn)
end
This page produced by UniDoc on 2021/04/15 @ 23:59:43.