[interchange-cvs] interchange - heins modified 4 files
interchange-cvs at icdevgroup.org
interchange-cvs at icdevgroup.org
Sun Jul 27 01:30:00 EDT 2003
User: heins
Date: 2003-07-27 04:30:54 GMT
Modified: code/UI_Tag if_mm.coretag
Modified: dist/foundation catalog.cfg
Modified: dist/foundation/products variable.txt
Modified: dist/lib/UI ui.cfg
Log:
* Add ability to edit pages using Mozilla composer, or any HTML editor
that can publish with an HTTP put. Includes ability to upload images
with the files, create new files, and more.
* ONLY operates on the area between <!-- BEGIN CONTENT --> and
<!-- END CONTENT -->.
* Pulls the page title from the <title></title> of the PUT page.
* If a new page is PUT, it is wrapped with the template used in
the nearest DirectoryIndex ("index" by default). If a new file
"trucks/chevy/mom.html" is created and does not exist, the following
files will be used as the template in this order if they exist:
trucks/chevy/index
trucks/index
index
* Update [if-mm ...] to have a "pagematch" and "filematch" function
that allows security checks based on the files and pages fields
in the access table. This allows certain users to have publish
permission only on certain image and page directories. For
instance, if the user "bubba" is only to edit files in the
"trucks" hierarchy, you would want in access:
username:bubba
files:images/trucks/
pages:trucks/
* Add action "admin_publish" that handles the PUT process. Requires
user be logged in as an admin, and requires
* Automatic RCS versioning if PUBLISH_DO_RCS variable is set. Can
stop publish if RCS error when PUBLISH_QUIT_ON_RCS_ERROR Variable
is set.
* Adding "ui_mozilla_edit=1" to the URL keeps ITL tags from being
interpolated within the BEGIN CONTENT/END CONTENT area. This
allows
* Automatically adjusts image paths in the uploaded file to be
relative to the directory the page is in. This allows individual
directories to use different sets of images and Mozilla won't
willy-nilly overwrite things in other directories.
* Handles most <a href="[area ...]"> things, I think. This can
probably be improved.
* Can prevent any publishing to the pages root if PUBLISH_NO_PAGE_ROOT
is set.
* TODO: Handle delivery and upload of Flash and other types of
things besides images.
* TODO: Add <meta ...> tag handling to allow component adjustments.
Revision Changes Path
1.3 +31 -0 interchange/code/UI_Tag/if_mm.coretag
rev 1.3, prev_rev 1.2
Index: if_mm.coretag
===================================================================
RCS file: /var/cvs/interchange/code/UI_Tag/if_mm.coretag,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- if_mm.coretag 7 Feb 2002 02:43:46 -0000 1.2
+++ if_mm.coretag 27 Jul 2003 04:30:54 -0000 1.3
@@ -71,6 +71,10 @@
tables tables
table tables
/;
+ my %prefix_func = qw/
+ filematch files
+ pagematch pages
+ /;
my $table = $CGI::values{mv_data_table} || $::Values->{mv_data_table};
@@ -92,12 +96,39 @@
my $file = $field || $Global::Variable->{MV_PAGE};
# strip trailing slashes for checks on directories
$file =~ s%/+$%%;
+#::logDebug("check=$check file=$file record=$record->{$check} prefix=$opt->{prefix}");
my @files = UI::Primitive::list_glob($record->{$check}, $opt->{prefix});
+#::logDebug("check yielded files=" . join(",", @files));
if(! @files) {
$status = '';
last CHECKIT;
}
$status = ui_check_acl("$file$extended", join(" ", @files));
+#::logDebug("check status=$status");
+ last CHECKIT;
+ }
+ if($check = $prefix_func{$func}) {
+ $status = '', last CHECKIT unless $record->{$check};
+ my $file = $field;
+ # strip trailing slashes for checks on directories
+#::logDebug("check=$check file=$file record=$record->{$check}");
+ my @allow = split /\s+/, $record->{$check};
+ $status = '';
+ for(@allow) {
+#::logDebug("check file=$file against allow=$_");
+ if(s/^\!//) {
+ if ($file =~ /^$_/) {
+#::logDebug("denied based on $_");
+ $status = '';
+ last CHECKIT;
+ }
+ }
+ else {
+ next unless $file =~ /^$_\b/;
+ $status = 1;
+ }
+ }
+#::logDebug("check Yielded status=$status");
last CHECKIT;
}
if($bool_func{$func} ) {
2.24 +3 -0 interchange/dist/foundation/catalog.cfg
rev 2.24, prev_rev 2.23
Index: catalog.cfg
===================================================================
RCS file: /var/cvs/interchange/dist/foundation/catalog.cfg,v
retrieving revision 2.23
retrieving revision 2.24
diff -u -r2.23 -r2.24
--- catalog.cfg 21 Jul 2003 17:53:37 -0000 2.23
+++ catalog.cfg 27 Jul 2003 04:30:54 -0000 2.24
@@ -111,6 +111,9 @@
ImageDir __IMAGE_DIR__/
ImageDirInternal http://__SERVER_NAME____IMAGE_DIR__/
+## This is put in so Mozilla's brain-dead composer refetch function won't fail
+DeliverImage yes
+
#==========================================================================#
# Here we set up the catalog theme.
2.32 +5 -0 interchange/dist/foundation/products/variable.txt
rev 2.32, prev_rev 2.31
Index: variable.txt
===================================================================
RCS file: /var/cvs/interchange/dist/foundation/products/variable.txt,v
retrieving revision 2.31
retrieving revision 2.32
diff -u -r2.31 -r2.32
--- variable.txt 25 Jun 2003 15:32:55 -0000 2.31
+++ variable.txt 27 Jul 2003 04:30:54 -0000 2.32
@@ -51,6 +51,11 @@
PHONE __MVC_PHONE__ Company
POSTAL_ACCEPTED 0 Payment
PO_ACCEPTED __MVC_PAYPO__ Payment
+PUBLISH_DO_RCS 0 Admin Control
+PUBLISH_NO_PAGE_ROOT 0 Admin Control
+PUBLISH_PUT_IMAGES images Admin Control
+PUBLISH_PUT_PAGES pages Admin Control
+PUBLISH_QUIT_ON_RCS_ERROR 0 Admin Control
SAMPLEHTML __MVC_SAMPLEHTML__ Directories and Paths
SAMPLEURL __MVC_SAMPLEURL__ Directories and Paths
SECURE_ENABLE __MVC_ENABLESECURE__ General
2.11 +268 -0 interchange/dist/lib/UI/ui.cfg
rev 2.11, prev_rev 2.10
Index: ui.cfg
===================================================================
RCS file: /var/cvs/interchange/dist/lib/UI/ui.cfg,v
retrieving revision 2.10
retrieving revision 2.11
diff -u -r2.10 -r2.11
--- ui.cfg 27 Jan 2003 19:03:36 -0000 2.10
+++ ui.cfg 27 Jul 2003 04:30:54 -0000 2.11
@@ -49,13 +49,18 @@
return unless $Vend::admin;
my $tmpd = $Vend::Cfg->{ScratchDir};
$tmpd .= "/previews/$Vend::SessionID";
+#::logDebug("tmpd = $tmpd");
$Vend::Cfg->{PreviewDir} = $tmpd if -d $tmpd;
+#::logDebug("PreviewDir=$Vend::Cfg->{PreviewDir}");
$::Variable->{ADL_SUFFIX} = $Vend::Cfg->{HTMLsuffix};
$::Variable->{ADL_PAGE} = $::Variable->{ADL_PAGE_TEMPLATE} || <<EOF;
[page href="admin/content_editor" form="
ui_name=[var MV_PAGE 1][var ADL_SUFFIX]
ui_type=page
"][loc]edit[/loc] [loc]page[/loc]</A>
+[page href="[var MV_PAGE 1]" form="
+ ui_mozilla_edit=1
+ "][loc]show tags[/loc]</A>
EOF
$::Variable->{ADL_COMPONENT} = $::Variable->{ADL_COMPONENT_TEMPLATE} || <<EOF;
@@ -65,6 +70,15 @@
"][loc]edit[/loc] [control component]</A>
EOF
+ $::Variable->{ADL_ITEM} = $::Variable->{ADL_ITEM_TEMPLATE} || <<EOF;
+<a href="[area
+ href=admin/item_edit
+ form=|
+ item_id=[item-code]
+ ui_return_to=index
+ |
+ ]">[loc]edit[/loc] [loc]item[/loc]</A>
+EOF
$::Variable->{ADL_MENU} = $::Variable->{ADL_MENU_TEMPLATE} || <<EOF;
<a class="[control link_class]"
href="[area
@@ -74,10 +88,264 @@
|
]">[loc]edit[/loc] [loc]menu[/loc]</A>
EOF
+
+ if($CGI::values{ui_mozilla_edit}) {
+ $::Pragma->{init_page} = 'show_tags_for_edit';
+ }
return;
}
EOS
+
+GlobalSub <<EOS
+sub show_tags_for_edit {
+ my $html = shift;
+ $$html =~ s{(<!--+\s*BEGIN\s+CONTENT\s*--+>)}{[strip reparse=0]$1};
+ $$html =~ s{(<!--+\s*END\s+CONTENT\s*--+>)}{$1\[/strip]};
+}
+EOS
+
+ActionMap admin_publish <<EOR
+sub {
+ require HTML::HeadParser;
+ my $path = shift;
+#::logDebug("Path is $path");
+
+ use vars qw/
+ $Tag
+ /;
+
+#::logDebug("env is " . ::uneval(Vend::Dispatch::http()->{env}));
+
+ $Vend::Extension and $path .= $Vend::Cfg->{HTMLsuffix};
+
+ unless($CGI::request_method eq 'PUT') {
+ $Tag->deliver('text/html', { status => "405 Not Implemented" }, 0);
+ logError("admin_publish expecting PUT.");
+ return;
+ }
+
+ unless($Vend::admin) {
+ $Tag->deliver('text/html', { status => "403 forbidden" }, 0);
+ logError("PUT by non-admin, quitting.");
+ return;
+ }
+
+ my $mimetype = Vend::Util::mime_type($path);
+
+ my $publish_dir;
+ my $icpage;
+ my $umask;
+ my $orig_umask;
+
+ if($mimetype eq 'text/html') {
+ $icpage = 1;
+ $publish_dir = $::Variable->{PUBLISH_PUT_PAGES} || 'pages';
+ unless($Tag->if_mm('pagematch', $path)) {
+ $Tag->deliver('text/html', { status => "403 forbidden" }, 0);
+ logError("User %s not authorized for page %s.", $Vend::username, $path);
+ return;
+ }
+ }
+ else {
+ $publish_dir = $::Variable->{PUBLISH_PUT_IMAGES} || 'images';
+ unless($Tag->if_mm('filematch', "$publish_dir/$path")) {
+ $Tag->deliver('text/html', { status => "403 forbidden" }, 0);
+ logError(
+ "User %s not authorized for file %s.",
+ $Vend::username,
+ "$publish_dir/$path",
+ );
+ return;
+ }
+ $umask = oct($::Variable->{PUBLISH_IMAGES_UMASK} || 2);
+ }
+
+ if( $::Variable->{PUBLISH_NO_PAGE_ROOT}
+ and $mimetype eq 'text/html'
+ and $path !~ m{/}
+ ) {
+ $Tag->deliver('text/html', { status => "403 forbidden" }, 0);
+ logError("PUT in top level of page directory not allowed.");
+ return;
+ }
+
+ my %header;
+
+ CREATEPAGE: {
+ my $top;
+ my $bottom;
+
+ last CREATEPAGE unless $icpage;
+
+ $::Pragma->{no_locale_parse} = 1;
+ my $origfile = readin($path);
+
+ my $dir = $path;
+ $dir =~ s:/[^/]+$::
+ or $dir = '';
+
+ GETPAGE: {
+ last GETPAGE if $origfile;
+ my $newpath = $path;
+ my $idx = $Vend::Cfg->{DirectoryIndex} || 'index';
+ while(! $origfile and $newpath =~ s:/?([^/]+)$::) {
+ $origfile = readin(Vend::File::catfile($newpath, $idx));
+ }
+ }
+ if(! $origfile) {
+ ::logDebug("Cannot find template file, publishing as is.");
+ last CREATEPAGE;
+ }
+ $origfile =~ s{(.*)\s*<!--+\s+BEGIN\s+CONTENT\s+--+>}{}s
+ and $top = $1;
+ $origfile =~ s{.*<!--+\s+END\s+CONTENT\s+--+>\s*}{}s
+ and $bottom = $origfile;
+ my $content = $$CGI::put_ref;
+
+ my $p = HTML::HeadParser->new();
+
+ $p->parse($content);
+ $header{page_title} = $p->header('title');
+#::logDebug("header title=$header{page_title} object" . ::uneval($p));
+ $top =~ s{(\[(seti?|tmpn?)\s+(\w+)\s*\])(.*?)(\[/\2\])}
+ {$1 . ($header{$3} || $4) . $5}eg;
+
+ $content =~ s{.*<!--+\s+BEGIN\s+CONTENT\s+--+>\s*}{}s
+ or $content =~ s:.*<body.*?>\s*::is;
+ $content =~ s{\s*<!--+\s+END\s+CONTENT\s+--+>.*}{}s
+ or $content =~ s:\s*</body\s*>.*::is;
+ $content =~ s/\r\n/\n/g;
+
+ my %strip_vars;
+ my $strip_init;
+
+ my $change_sub = sub {
+ my $url = shift;
+ return $url if $url =~ m{^\w+:};
+ return $url if $url =~ m{^[[/]};
+ my @parts = split m{/}, $dir;
+ while($url =~ s{^../}{}) {
+ splice @parts, -1, 1;
+ }
+ my $newdir = join "/", @parts;
+ $url = "$newdir/$url" if $newdir;
+
+ my $arg;
+ my @args;
+ my @out;
+ ($url, $arg) = split /[?&]/, $url, 2;
+ @args = split $Global::UrlSplittor, $arg;
+ if(@args) {
+ for(@args) {
+ my ($var, $val) = split /=/, $_, 2;
+ next if $strip_vars{$var};
+ push @out, "$var=" . unhexify($_);
+ }
+ my $fstr = join "\n", @out;
+ return qq{[area href='$url' form=|$fstr|]};
+ }
+ return qq{[area $url]};
+ };
+
+ 1 while $content =~ s{(<\w+[^>]*\s+[-\w]+\s*=\s*")([^"]*\%5b.*?\%5d)}
+ {$1 . unhexify($2)}ie;
+ if($dir) {
+ $dir =~ s:/*$:/:;
+ $content =~ s{(<a\s+[^>]*href\s*=\s*)(["'])(\.\.[^'"]+)\2}
+ {$1 . $2 . $change_sub->($3) . $2}gei;
+ $content =~ s#(<i\w+\s+[^>]*?src=")(?!\w+:)([^/'][^"]+)#
+ $1 . $dir . $2#ige;
+ $content =~ s#(<body\s+[^>]*?background=")(?!\w+:)([^/'][^"]+)#
+ $1 . $dir . $2#ige;
+ $content =~ s#(<t(?:[dhr]|able)\s+[^>]*?background=")(?!\w+:)([^/'][^"]+)#
+ $1 . $dir . $2#ige;
+ }
+
+ $$CGI::put_ref = join "\n",
+ $top,
+ '<!-- BEGIN CONTENT -->',
+ $content,
+ '<!-- END CONTENT -->',
+ $bottom;
+ }
+
+ if($::Variable->{PUBLISH_TO_PREVIEWS}) {
+ $Vend::Cfg->{PreviewDir} ||=
+ catfile($Vend::Cfg->{ScratchDir}, 'previews', $Vend::SessionID);
+ $publish_dir = $Vend::Cfg->{PreviewDir};
+ $publish_dir =~ s{^$Vend::Cfg->{VendRoot}/*}{};
+ }
+
+#::logDebug("PUBLISH_DIR=$publish_dir FILE=$path");
+
+ my $fn = catfile($publish_dir, $path);
+
+ $orig_umask = umask($umask) if $umask;
+
+ if($icpage and $::Variable->{PUBLISH_DO_RCS} and -f $fn) {
+ ## Make the RCS directory if not there
+ my $dir;
+ $fn =~ m{(.*)/};
+ $dir = "$1/RCS";
+ File::Path::mkpath($dir) if ! -d $dir;
+
+ my $msg = errmsg("Change by %s published via PUT.", $Vend::username);
+ my @rcs_cmd = (
+ qq{ci -m"$msg" $fn >/dev/null 2>/dev/null},
+ qq{co -l $fn >/dev/null 2>/dev/null},
+ );
+
+ # See if in RCS already, check in initial if not
+ system(qq{rlog $fn >/dev/null 2>/dev/null});
+ if($?) {
+#::logDebug("RCS version was not there.");
+ my $m = $header{page_title} || 'New page';
+ $m =~ s/"/\\"/g;
+ $rcs_cmd[0] = qq{ci -i1.1 -t-"$m" $fn >/dev/null 2>/dev/null};
+ ## Do nothing, there was already a version
+ }
+ else {
+#::logDebug("RCS version previously checked in.");
+ ## Don't need to check in, already done
+ }
+ for(@rcs_cmd) {
+#::logDebug("RCS command: $_");
+ system $_;
+ if($?) {
+ logError("PUT RCS error on command '%s': %s", $_, $!);
+ if ($::Variable->{PUBLISH_QUIT_ON_RCS_ERROR}) {
+ $Tag->deliver('text/html', { status => "500 Server Error" }, 0);
+ umask($orig_umask) if defined $orig_umask;
+ return;
+ }
+ }
+ }
+ }
+
+#::logDebug("Getting ready to put $fn.");
+
+ my $existing = -f $fn;
+
+ unless($Tag->write_relative_file($fn, $$CGI::put_ref)) {
+ $Tag->deliver('text/html', { status => "500 Server Error" }, 0);
+ logError("PUT of $fn failed, write error.");
+ umask($orig_umask) if defined $orig_umask;
+ return;
+ }
+
+ umask($orig_umask) if defined $orig_umask;
+
+ $Vend::Session->{put_files} ||= [];
+ push (@{$Vend::Session->{put_files}}, $path);
+
+ my $status = $existing ? '204 OK' : '201 OK';
+ ::logError("put of %s succeeded, status=$status.", $fn);
+
+ $Tag->deliver('text/html', { status => $status}, 1);
+ return;
+}
+EOR
# user tags
include lib/UI/vars/*
More information about the interchange-cvs
mailing list