Loading ...
Sorry, an error occurred while loading the content.

A nifty code sample to share

Expand Messages
  • Brat Wizard
    I ve been meaning for a long time to release some code samples-- here is one I especially like for making menus and navbars in html-- same code will work for
    Message 1 of 16 , Sep 17, 2002
    View Source
    • 0 Attachment
      I've been meaning for a long time to release some code samples-- here is one I
      especially like for making menus and navbars in html-- same code will work
      for either.

      A caveat: I use several custom modules which hides some stuff- most notably
      the Page object, which is basically a hash of hashes that contain the
      menu-item data, as well as an array of pages (items in a Page object) which
      keeps the correct page-order. The general structure of a page-item is like
      this:

      name => undef, # name of page item (eg. 'contact')
      admin => 0, # 1=Admin-Only
      caption => undef, # page caption (eg. "Contact Us")
      url => undef, # what to do if clicked eg: http://someurl
      type => 'user', # User or Prot (Prot=protected & can't edit)
      origin => 'user', # User or Int (Int=internal)
      active => 0, # mark inactive by default

      And not all of these items are relevant to this routine. So, that said, this
      snippet of code-- which is meant more for its idea value than its particular
      usefulness as written-- (it works well in my apps but you won't have all the
      supporting stuff to make it work out of the box). This bit of code will allow
      you to very easily specify an html menu/navbar structure and have the
      selected item behave differently, and to specify the menu separator (if any).
      It easily lends itself to horizontal and vertical menus and its html-like
      (xml-ish) syntax is like so (a simplified vertical example):

      <table><tr><td>
      <my:menu selected="$$args{cmd}">
      <sel><b><a href="__URL__">__CAPTION__</a></b><br></sel>
      <norm><a href="__URL__">__CAPTION__</a><br></norm>
      </my:menu>
      </td></tr></table>

      This produces a very attractive (albeit simple) vertical menu. What's
      important is to notice the <sel>, <norm>, and (if present), <sep> tags (and
      they need to be closed). ANY legal html/javascript code (or anything else for
      that matter that can be expressed as a string) can be put between the tags.
      For example, in more complicated menus, I often use javascript to do button
      rollover effects and the like.

      The function presented below will take everything (in uppercase) surrounded by
      two underscores (ie. '__FIELD__') and attempt to match it to its
      corresponding (lower-case) field in the page-item object (or your own
      substituted hash structure).

      If the <sep> tag is present, it will be used between the menu/navbar items and
      will separate the items however you say. I often just use something like
      <sep>|</sep> (vertical bar) or <sep>  </sep> (a couple of spaces),
      but it can be anything html.

      To make this work, you have to be using the XMLSubsMatch setting in the
      .htaccess or apache config file (wherever you set your other ASP config
      vars). Mine looks like this:

      PerlSetVar XMLSubsMatch my:\w+

      This causes anything beginning with 'my:' in my .html/.asp files to be
      interpreted (or attempted anyway) as a sub-routine reference. The args
      supplied inside the opening tag itself are passed to the subroutine as
      '$args' (or whatever you want to call it-- the first argument passed). The
      text (if any) between the tags is passed as the second ($body). Such that:

      <my:parseme somefield="someval">
      Whatever you want to pass as the body goes here
      </my:parseme>

      This is all documented better on the main ASP site.

      One thing to note that is NOT mentioned on the ASP site-- apparently the
      parsing algorithm doesn't know how to handle values that are NOT enclosed in
      quotes. Html does not require quotes as long as the value contains no spaces
      and only alphanumeric characters. You can't do that here. The other thing to
      point out is that any perl variables (eg. $myvar) are NOT escaped in the
      usual apache::asp way, (<%=$myvar%>) but instead are just simply passed
      between the quotes. Personally I think this is an inconsistancy, and one that
      should be dealt with so that clueless users who write html pages using custom
      tags don't accidently expose the workings of apache::asp. An alternative
      might be to allow a secondary syntax that could only be used as subroutine
      references-- eg. [% stuff %]. I can understand the depth of the syntax and
      coding problems surrounding this issue-- especially when the subject of
      nesting comes up... I'm not complaining, just tossing in my 2 cents and
      wishing there was a way to keep the functional aspect without exposing ASP to
      the clueless user (or malicious web hacker for that matter).

      Anyway, fwiw, here is the routine below. You can see an example of it in
      operation at: stores.wizard.org/wizorg, stores.wizard.org/wizcomp, and
      stores.wizard.org/dots (I'm not sure that Dot has her store completely set up
      and ready to go but you can see the menu anyway).

      I hope this helps someone! :)

      John Whitten
      brat@...
      Wizard.Org, Inc.


      ##----------------------------------------------------------------------------
      sub my::navbar { my::menu(@_) }
      sub my::menu {
      my ($args, $body) = @_;
      my $norm = qq{<a href="__URL__">__CAPTION__</a><br>};
      my $sel = qq{<b><a href="__URL__">__CAPTION__</a></b><br>};
      my $sep = '';
      my $themeurl = "$URL{theme}/$Store->{theme}/images";

      if ($body =~ /<norm>/i) {
      $body =~ /<norm>(.*?)<\/norm>/i; # normal cell
      $norm = $1;
      }
      if ($body =~ /<sel>/i) {
      $body =~ /<sel>(.*?)<\/sel>/i; # selected cell
      $sel = $1;
      }
      if ($body =~ /<sep>/i) {
      $body =~ /<sep>(.*?)<\/sep>/i; # divider cell
      $sep = $1;
      }

      $$args{selected} = lc($$args{selected});
      my $start = 0;
      foreach (@{$Store->{pages}}) {
      my $page = $Store->{pagedata}->findPage($_);
      next if (isPermitted() == 0 && $page->val('admin') == 1);
      my $name = $page->val('name');

      my $caption = $page->val('caption') || $name;
      my $url = $page->val('url');
      my $selected = ($name eq $$args{selected})?1:0;

      $url = $page->val('url');
      $url = "/$storeid/$name" if ($url eq '');

      print "$sep\n" if ($sep ne '' && $start++ > 0);
      my $str = ($selected == 1)?$sel:$norm;
      $str =~ s/__NAME__/$name/gie;
      $str =~ s/__URL__/$url/gie;
      $str =~ s/__CAPTION__/$caption/gie;
      print "$str\n";
      }
      }


      --

      --------------------------------------------------------------------------------
      Check out http://www.Wizard.Org for great deals on Electronic Parts
      *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
      --------------------------------------------------------------------------------
      ** Affordable Online Store w/Merchant Card Processing & Paypal **
      Write to us: sales@... -- Get your Store Online Today!
      --------------------------------------------------------------------------------



      ---------------------------------------------------------------------
      To unsubscribe, e-mail: asp-unsubscribe@...
      For additional commands, e-mail: asp-help@...
    • Brat Wizard
      Um- minor correction- I slightly misspoke-- I was confusing this with another module I have. This example _only_ matches the URL, CAPTION, and NAME fields from
      Message 2 of 16 , Sep 17, 2002
      View Source
      • 0 Attachment
        Um- minor correction-

        I slightly misspoke-- I was confusing this with another module I have. This
        example _only_ matches the URL, CAPTION, and NAME fields from the hash. Sorry
        for any confusion.

        John


        On Tuesday 17 September 2002 03:27 am, Brat Wizard spewed into the ether:
        > I've been meaning for a long time to release some code samples-- here is
        > one I especially like for making menus and navbars in html-- same code will
        > work for either.
        >
        > A caveat: I use several custom modules which hides some stuff- most notably
        > the Page object, which is basically a hash of hashes that contain the
        > menu-item data, as well as an array of pages (items in a Page object) which
        > keeps the correct page-order. The general structure of a page-item is like
        > this:
        >
        > name => undef, # name of page item (eg. 'contact')
        > admin => 0, # 1=Admin-Only
        > caption => undef, # page caption (eg. "Contact Us")
        > url => undef, # what to do if clicked eg: http://someurl
        > type => 'user', # User or Prot (Prot=protected & can't
        > edit) origin => 'user', # User or Int (Int=internal)
        > active => 0, # mark inactive by default
        >
        > And not all of these items are relevant to this routine. So, that said,
        > this snippet of code-- which is meant more for its idea value than its
        > particular usefulness as written-- (it works well in my apps but you won't
        > have all the supporting stuff to make it work out of the box). This bit of
        > code will allow you to very easily specify an html menu/navbar structure
        > and have the selected item behave differently, and to specify the menu
        > separator (if any). It easily lends itself to horizontal and vertical menus
        > and its html-like (xml-ish) syntax is like so (a simplified vertical
        > example):
        >
        > <table><tr><td>
        > <my:menu selected="$$args{cmd}">
        > <sel><b><a href="__URL__">__CAPTION__</a></b><br></sel>
        > <norm><a href="__URL__">__CAPTION__</a><br></norm>
        > </my:menu>
        > </td></tr></table>
        >
        > This produces a very attractive (albeit simple) vertical menu. What's
        > important is to notice the <sel>, <norm>, and (if present), <sep> tags (and
        > they need to be closed). ANY legal html/javascript code (or anything else
        > for that matter that can be expressed as a string) can be put between the
        > tags. For example, in more complicated menus, I often use javascript to do
        > button rollover effects and the like.
        >
        > The function presented below will take everything (in uppercase) surrounded
        > by two underscores (ie. '__FIELD__') and attempt to match it to its
        > corresponding (lower-case) field in the page-item object (or your own
        > substituted hash structure).
        >
        > If the <sep> tag is present, it will be used between the menu/navbar items
        > and will separate the items however you say. I often just use something
        > like <sep>|</sep> (vertical bar) or <sep>  </sep> (a couple of
        > spaces), but it can be anything html.
        >
        > To make this work, you have to be using the XMLSubsMatch setting in the
        > .htaccess or apache config file (wherever you set your other ASP config
        > vars). Mine looks like this:
        >
        > PerlSetVar XMLSubsMatch my:\w+
        >
        > This causes anything beginning with 'my:' in my .html/.asp files to be
        > interpreted (or attempted anyway) as a sub-routine reference. The args
        > supplied inside the opening tag itself are passed to the subroutine as
        > '$args' (or whatever you want to call it-- the first argument passed). The
        > text (if any) between the tags is passed as the second ($body). Such that:
        >
        > <my:parseme somefield="someval">
        > Whatever you want to pass as the body goes here
        > </my:parseme>
        >
        > This is all documented better on the main ASP site.
        >
        > One thing to note that is NOT mentioned on the ASP site-- apparently the
        > parsing algorithm doesn't know how to handle values that are NOT enclosed
        > in quotes. Html does not require quotes as long as the value contains no
        > spaces and only alphanumeric characters. You can't do that here. The other
        > thing to point out is that any perl variables (eg. $myvar) are NOT escaped
        > in the usual apache::asp way, (<%=$myvar%>) but instead are just simply
        > passed between the quotes. Personally I think this is an inconsistancy, and
        > one that should be dealt with so that clueless users who write html pages
        > using custom tags don't accidently expose the workings of apache::asp. An
        > alternative might be to allow a secondary syntax that could only be used as
        > subroutine references-- eg. [% stuff %]. I can understand the depth of the
        > syntax and coding problems surrounding this issue-- especially when the
        > subject of nesting comes up... I'm not complaining, just tossing in my 2
        > cents and wishing there was a way to keep the functional aspect without
        > exposing ASP to the clueless user (or malicious web hacker for that
        > matter).
        >
        > Anyway, fwiw, here is the routine below. You can see an example of it in
        > operation at: stores.wizard.org/wizorg, stores.wizard.org/wizcomp, and
        > stores.wizard.org/dots (I'm not sure that Dot has her store completely set
        > up and ready to go but you can see the menu anyway).
        >
        > I hope this helps someone! :)
        >
        > John Whitten
        > brat@...
        > Wizard.Org, Inc.
        >
        >
        > ##-------------------------------------------------------------------------
        >--- sub my::navbar { my::menu(@_) }
        > sub my::menu {
        > my ($args, $body) = @_;
        > my $norm = qq{<a href="__URL__">__CAPTION__</a><br>};
        > my $sel = qq{<b><a href="__URL__">__CAPTION__</a></b><br>};
        > my $sep = '';
        > my $themeurl = "$URL{theme}/$Store->{theme}/images";
        >
        > if ($body =~ /<norm>/i) {
        > $body =~ /<norm>(.*?)<\/norm>/i; # normal cell
        > $norm = $1;
        > }
        > if ($body =~ /<sel>/i) {
        > $body =~ /<sel>(.*?)<\/sel>/i; # selected cell
        > $sel = $1;
        > }
        > if ($body =~ /<sep>/i) {
        > $body =~ /<sep>(.*?)<\/sep>/i; # divider cell
        > $sep = $1;
        > }
        >
        > $$args{selected} = lc($$args{selected});
        > my $start = 0;
        > foreach (@{$Store->{pages}}) {
        > my $page = $Store->{pagedata}->findPage($_);
        > next if (isPermitted() == 0 && $page->val('admin') == 1);
        > my $name = $page->val('name');
        >
        > my $caption = $page->val('caption') || $name;
        > my $url = $page->val('url');
        > my $selected = ($name eq $$args{selected})?1:0;
        >
        > $url = $page->val('url');
        > $url = "/$storeid/$name" if ($url eq '');
        >
        > print "$sep\n" if ($sep ne '' && $start++ > 0);
        > my $str = ($selected == 1)?$sel:$norm;
        > $str =~ s/__NAME__/$name/gie;
        > $str =~ s/__URL__/$url/gie;
        > $str =~ s/__CAPTION__/$caption/gie;
        > print "$str\n";
        > }
        > }

        --

        --------------------------------------------------------------------------------
        Check out http://www.Wizard.Org for great deals on Electronic Parts
        *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
        --------------------------------------------------------------------------------
        ** Affordable Online Store w/Merchant Card Processing & Paypal **
        Write to us: sales@... -- Get your Store Online Today!
        --------------------------------------------------------------------------------



        ---------------------------------------------------------------------
        To unsubscribe, e-mail: asp-unsubscribe@...
        For additional commands, e-mail: asp-help@...
      • Josh Chamas
        ... I have created the ability in the system to have includes shared pretty easily with the Share:: namespace, but haven t put anything in there yet. This
        Message 3 of 16 , Sep 17, 2002
        View Source
        • 0 Attachment
          >>I've been meaning for a long time to release some code samples-- here is
          >>one I especially like for making menus and navbars in html-- same code will
          >>work for either.
          >>

          I have created the ability in the system to have includes shared
          pretty easily with the Share:: namespace, but haven't put anything
          in there yet. This namespace is Apache::ASP::Share more generally,
          so this could then a module like Apache::ASP::Share::Wizard,
          which might export a menu() subroutine, that someone could then
          wire pretty easily into their XMLSubs package namespace?
          Then this sub could be distributed with Apache::ASP.

          Alternatively, you could publish this to CPAN as the
          Apache::ASP::Share::Wizard package, and put everything you
          want in there at your leisure. Useful templates can be loaded
          from that like $Response->Include("Share::Wizard/template.inc"),
          and the subs/objects can be imported normally. That would
          be cool if at the end of an install, someone could
          man/perldoc Apache::ASP::Share::Wizard

          I wish I had a better structured interface for this, or
          a XMLSubs namespace mapping ability, but I have neither yet
          hooked into Apache::ASP. The Share:: include namespace
          was hard enough to work out as it was.

          >><table><tr><td>
          >><my:menu selected="$$args{cmd}">
          >> <sel><b><a href="__URL__">__CAPTION__</a></b><br></sel>
          >> <norm><a href="__URL__">__CAPTION__</a><br></norm>
          >></my:menu>
          >></td></tr></table>

          Did you know that in the body of an XMLSubs, you can do things
          like <%= $Object->URL %> instead of the __URL__. I begin to
          see how it would be nice to offer a set of standard XMLSubs
          that can do such things as __TOKEN__ post processing as standard.
          I have thought about ports a subset of the standard JSP taglibs
          for similar effect so we can have a nice default tag library
          to work with too, but have some namespace issues to work though first.

          >>One thing to note that is NOT mentioned on the ASP site-- apparently the
          >>parsing algorithm doesn't know how to handle values that are NOT enclosed
          >>in quotes. Html does not require quotes as long as the value contains no
          >>spaces and only alphanumeric characters. You can't do that here. The other
          >>thing to point out is that any perl variables (eg. $myvar) are NOT escaped
          >>in the usual apache::asp way, (<%=$myvar%>) but instead are just simply
          >>passed between the quotes. Personally I think this is an inconsistancy, and

          In Apache::ASP v3.0 ( & 2.9xx betas ), there will be the default
          syntax of <my:sub arg1="<%= $var %>" /> instead of the <my:sub arg1="$var" />
          today. To retain backwared compatibility, there will be an XMLSubsPerlArgs
          config that can be set to activate the old method for backwards compatibility.

          Other big things will happen in 3.0 like UseStrict becoming default,
          which is why 3.0 will be the release for them. I have already code forked
          off the 2.xx branch internally from 3.0 so I can keep doing fixes there
          separate from the bigger changes in 3.0.

          Thanks for sharing that interesting code sample.

          Regards,

          Josh


          ---------------------------------------------------------------------
          To unsubscribe, e-mail: asp-unsubscribe@...
          For additional commands, e-mail: asp-help@...
        • Brat Wizard
          ... So basically you re saying create a directory on my system /usr/lib/ /Apache/ASP/Share/Wizard and put my modules (*.pm) in there... Then
          Message 4 of 16 , Sep 17, 2002
          View Source
          • 0 Attachment
            On Tuesday 17 September 2002 01:45 pm, you muttered:
            > >>I've been meaning for a long time to release some code samples--
            >
            > I have created the ability in the system to have includes shared
            > pretty easily with the Share:: namespace, but haven't put anything
            > in there yet. This namespace is Apache::ASP::Share more generally,
            > so this could then a module like Apache::ASP::Share::Wizard,
            > which might export a menu() subroutine, that someone could then
            > wire pretty easily into their XMLSubs package namespace?
            > Then this sub could be distributed with Apache::ASP.

            So basically you're saying create a directory on my system

            /usr/lib/<wherever perl goes>/Apache/ASP/Share/Wizard

            and put my modules (*.pm) in there...

            Then I could:

            use Apache::ASP::Share::Wizard::MyModule;


            > Alternatively, you could publish this to CPAN as the
            > Apache::ASP::Share::Wizard package, and put everything you
            > want in there at your leisure. Useful templates can be loaded
            > from that like $Response->Include("Share::Wizard/template.inc")
            > and the subs/objects can be imported normally. That would
            > be cool if at the end of an install, someone could
            > man/perldoc Apache::ASP::Share::Wizard

            Heh, is that a hint?? ;)

            I have tons of '#' comments sprinkled throughout my code but never got in the
            habit of doing the perldoc way. Perhaps now is a good time to get started.
            You may be doing me a back-handed favor ;)


            > I wish I had a better structured interface for this, or
            > a XMLSubs namespace mapping ability, but I have neither yet
            > hooked into Apache::ASP. The Share:: include namespace
            > was hard enough to work out as it was.
            >
            > >><table><tr><td>
            > >><my:menu selected="$$args{cmd}">
            > >> <sel><b><a href="__URL__">__CAPTION__</a></b><br></sel>
            > >> <norm><a href="__URL__">__CAPTION__</a><br></norm>
            > >></my:menu>
            > >></td></tr></table>
            >
            > Did you know that in the body of an XMLSubs, you can do things
            > like <%= $Object->URL %> instead of the __URL__.

            Unless I misunderstand your meaning, I don't think that would do what I want
            in this instance since the __TOKENS__ are not being processed until they get
            inside the subroutine, and more to the point, the values of the tokens are
            undefined until given meaning (scoped into context) by the page-item
            iteration loop. Also, what you're suggesting takes place before the
            subroutine anyway... yes?


            > I begin to
            > see how it would be nice to offer a set of standard XMLSubs
            > that can do such things as __TOKEN__ post processing as standard.

            Yes, that would be very nice. BTW, I have another, slightly more generic
            version of the menu/navbar routine that does something similar to what you're
            suggesting. It retrieves a row-hash from a DBI datasource and allows
            __TOKENS__ to be substituted if they exist in the row-hash. (This is the
            function I was thinking last night when I was doing my description). I'm
            planning on releasing it as well. Perhaps that will give you, or others some
            ideas.

            If you REALLY REALLY wanted to do the world a favor (well, the asp community
            anyway)-- make up a nice set of methods to abstract/obscure db results
            paging. That is arguably one of the BIGGEST pain-in-the-ass chores there is
            as well as an oft-used construct. Surely there could be a better way. ;)


            > I have thought about ports a subset of the standard JSP taglibs
            > for similar effect so we can have a nice default tag library
            > to work with too, but have some namespace issues to work though first.

            Hmm- thanks for the clue, I will go research them and bone up. Wasn't aware
            there was some sort of standard developing.


            > >>One thing to note that is NOT mentioned on the ASP site-- apparently the
            > >>parsing algorithm doesn't know how to handle values that are NOT enclosed
            > >>in quotes. Html does not require quotes as long as the value contains no
            > >>spaces and only alphanumeric characters. You can't do that here. The
            > >> other thing to point out is that any perl variables (eg. $myvar) are NOT
            > >> escaped in the usual apache::asp way, (<%=$myvar%>) but instead are just
            > >> simply passed between the quotes. Personally I think this is an
            > >> inconsistancy, and
            >
            > In Apache::ASP v3.0 ( & 2.9xx betas ), there will be the default
            > syntax of <my:sub arg1="<%= $var %>" /> instead of the <my:sub arg1="$var"
            > /> today.

            Is there any way to handle the "quotes-not-required" bit? (Probably not, but
            asking anyway ;)

            Its only a minor annoyance to me personally (and is always good for a santyx
            error when I go to run the code ;) But my real concern-- and none of the
            above really has anything to do with it, since use of the <% %> tags is the
            real issue-- is that if an end-user (someone who is allowed to make html
            pages using custom tags, etc) is really savvy and perceptive, they could
            fathom out some of the inner workings of the apache/perl engine and
            application environment and there is a potential security issue in all this.

            Since any legal perl code can be operated between <% %> tags, a
            suitably-mischievous person could potentially access, (ab)use, or hijack some
            portion of the system (that the apache server process has permissions for).
            If you (the programmer/webmaster) keep complete control over the pages you're
            safe, but you can't safely share it with a unknown (eg non-trusted) user, and
            this is a real shame because the potential for giving the end-user some
            really nifty items is there (as well as a mechanism for obscuring nasty or
            complex code/issues.

            On the other hand, the opportunities for mischief are greatly diminished if
            only through obscurity-- the end-user isn't likely to have access to the
            source code of my application nor knowledge of the intimate data structures
            necessary to do a lot of damage to the application directly-- though I myself
            have been known to enage in some "perceptive spleunking" from time-to-time.
            You never know what you can dredge up that way ;)


            >To retain backward compatibility, there will be an
            > XMLSubsPerlArgs config that can be set to activate the old method for
            > backwards compatibility.

            I think the new method will be a nice change-- a move toward a more
            consistent, and therefore intuitive, interface.


            > Other big things will happen in 3.0 like UseStrict becoming default,
            > which is why 3.0 will be the release for them. I have already code forked
            > off the 2.xx branch internally from 3.0 so I can keep doing fixes there
            > separate from the bigger changes in 3.0.
            >
            > Thanks for sharing that interesting code sample.

            Not a problem. I plan on sharing some more as time permits.


            Now I have a question for you... ever since I first started programming ASP
            projects I have been trying to fathom how to use the "default module" that
            goes along with a project?? Its sorta seems like a dingleberry but I've
            always included it mostly out of habit but partly for not knowing better.
            Lately I've been looking through it with a more critical view and I just
            can't see how its relevant. It appears to be just setting up for some
            hypothetical module that might be created, perhaps to run CGI-ish code.

            ex.

            #! /bin/perl

            package WIZORG;
            use File::Basename;

            sub new {
            my($request) = $main::Request;
            my($env) = $request->ServerVariables();

            my $basename = &File::Basename::basename($0);
            my($title) = join(': ', "WIZORG", $basename);
            my($self) = bless {
            bgcolor => white,
            env => $env,
            title => $title,
            file => $basename
            };

            $self;
            }

            1;


            So... Is it safe to junk it or have I missed a core concept?


            John

            -
            --------------------------------------------------------------------------------
            Check out http://www.Wizard.Org for great deals on Electronic Parts
            *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
            --------------------------------------------------------------------------------
            ** Affordable Online Store w/Merchant Card Processing & Paypal **
            Write to us: sales@... -- Get your Store Online Today!
            --------------------------------------------------------------------------------



            ---------------------------------------------------------------------
            To unsubscribe, e-mail: asp-unsubscribe@...
            For additional commands, e-mail: asp-help@...
          • Josh Chamas
            ... Only if you wanted to share them with others. You could start developing them with use lib qw(some_dir); use Apache::ASP::Share::Wizard; Then you would
            Message 5 of 16 , Sep 17, 2002
            View Source
            • 0 Attachment
              Brat Wizard wrote:
              >
              > So basically you're saying create a directory on my system
              >
              > /usr/lib/<wherever perl goes>/Apache/ASP/Share/Wizard
              >
              > and put my modules (*.pm) in there...
              >

              Only if you wanted to share them with others. You
              could start developing them with

              use lib qw(some_dir);
              use Apache::ASP::Share::Wizard;

              Then you would create the directory structure
              of some_dir/Apache/ASP/Share/ and drop in Wizard.pm

              Then when it some time to create your own CPAN distribution,
              its all ready to go.

              > Then I could:
              >
              > use Apache::ASP::Share::Wizard::MyModule;
              >

              Right, create some_dir/Apache/ASP/Share/Wizared
              and drop MyModule into it too.

              >
              > I have tons of '#' comments sprinkled throughout my code but never got in the
              > habit of doing the perldoc way. Perhaps now is a good time to get started.
              > You may be doing me a back-handed favor ;)
              >

              From Mythical Man Month, making a bit of code well documented
              a reusable can take 3x the time, so only do so if you feel
              like its worth the effort. Its will pay off long term should
              anyone else ever have to look at your code, and doing a CPAN
              type distribution can make you a better developer besides,
              especially with the peer review you can garner.

              >>Did you know that in the body of an XMLSubs, you can do things
              >>like <%= $Object->URL %> instead of the __URL__.
              >
              >
              > Unless I misunderstand your meaning, I don't think that would do what I want
              > in this instance since the __TOKENS__ are not being processed until they get
              > inside the subroutine, and more to the point, the values of the tokens are
              > undefined until given meaning (scoped into context) by the page-item
              > iteration loop. Also, what you're suggesting takes place before the
              > subroutine anyway... yes?
              >

              Right, that would not work then.

              >
              > If you REALLY REALLY wanted to do the world a favor (well, the asp community
              > anyway)-- make up a nice set of methods to abstract/obscure db results
              > paging. That is arguably one of the BIGGEST pain-in-the-ass chores there is
              > as well as an oft-used construct. Surely there could be a better way. ;)
              >

              Right, mine too. I think others have tried to do this well,
              but have no links for you on this at the moment.

              >
              > Is there any way to handle the "quotes-not-required" bit? (Probably not, but
              > asking anyway ;)
              >

              For XMLSubs to evolve, I believe no unfortunately. XML attributes
              need to be quoted, and I try to have them live up to their
              name as well as possible.

              > Its only a minor annoyance to me personally (and is always good for a santyx
              > error when I go to run the code ;) But my real concern-- and none of the
              > above really has anything to do with it, since use of the <% %> tags is the
              > real issue-- is that if an end-user (someone who is allowed to make html
              > pages using custom tags, etc) is really savvy and perceptive, they could
              > fathom out some of the inner workings of the apache/perl engine and
              > application environment and there is a potential security issue in all this.
              >

              Yes. There is nothing particularly dumbed down or secure about writing
              ASP pages. For example, what would happen if a user did:

              <% `rm -rf /`; %>

              There is nothing in the system that will protect against this.
              I have considered creating some tag that would NULL all <% %>
              blocks in a page being parsed, and only allow for XMLSubs to
              be used by an end user. I would only add this after 3.0
              release at this point, and it could be used to secure XMLSubs
              that are only interpolating arguments in <%= %>, not the 2.xx
              XMLSubsPerlArgs type functionality.

              > Since any legal perl code can be operated between <% %> tags, a
              > suitably-mischievous person could potentially access, (ab)use, or hijack some
              > portion of the system (that the apache server process has permissions for).
              > If you (the programmer/webmaster) keep complete control over the pages you're
              > safe, but you can't safely share it with a unknown (eg non-trusted) user, and
              > this is a real shame because the potential for giving the end-user some
              > really nifty items is there (as well as a mechanism for obscuring nasty or
              > complex code/issues.

              Generally, mod_perl is not secure for arbitrary users in a shared
              hosting environment because the code is always run as the web server.
              This will supposedly be changed in apache 2.0 when they add per user
              per virtual host based process model. However, until then the most
              secure you can run Apache::ASP is to use the asp-perl script to
              run a script in CGI mode. Its slow, but it works, and you could
              give your users the features, while keeping things secure with
              per user CGI execution functionality.

              > Now I have a question for you... ever since I first started programming ASP
              > projects I have been trying to fathom how to use the "default module" that
              > goes along with a project?? Its sorta seems like a dingleberry but I've
              > always included it mostly out of habit but partly for not knowing better.
              > Lately I've been looking through it with a more critical view and I just
              > can't see how its relevant. It appears to be just setting up for some
              > hypothetical module that might be created, perhaps to run CGI-ish code.
              >

              If you have an object that is your Application object, or Model in MVC,
              then you can abstract things away from your views which are the ASP scripts.
              The controller is Apache::ASP itself, plus whatever you add to
              Script_OnStart that might affect how the script gets loaded, if at all!

              This application object can then be used to centralize & streamline
              code bits that occur all over your site. For example, instead of
              having a register_user.inc include that you call at the right time,
              you can do instead:

              <% $App->register_user; %>

              This $App object might be of class Wizard::App that other objects
              subclass off of, and you might also be able to call it from nightly
              running cron & other various back end business logic that have
              nothing to do with ASP scripts.

              Though in breaking of the MVC paradigm, I often also do nice little
              view shorthands & place them in the app object for the web site like:

              # global.asa
              use vars qw($App); # declare global
              sub Script_OnStart {
              $App = Wizard::App::ASP->new(Request => $Request);
              # $App->{form} get created below
              }

              # Wizard::App::ASP
              @ISA = qw(Wizard::App);
              package Wizard::App::ASP;
              sub new {
              my($class, %args) = @_;
              $args{Request} || die("no Request object to new");

              my $self = $class->SUPER::new(%args);
              my $Request = $args{Request};
              $self->{form} = $Request->Form;
              $self->{query} = $Request->QueryString;

              $self;
              }

              and so on. Then you can reference this kind of data
              differently in your scripts like:

              <%= $App->{form} %>

              with the added advantage that the app object already
              has the HTTP data available to it if you need it in
              on of its methods. For something like register_user,
              you might have a core App object that takes params:

              package Wizard::App;
              sub register_user {
              my($self, %args) = @_;
              ...
              }

              & then in the ASP subclass, you can override it with
              the right values:

              sub register_user {
              my $self = shift;
              # error checking code on params
              $self->SUPER::register_user(%{$self->{form}});
              }

              You don't need to init the object with the $Request->Form
              data at Script_OnStart however, as you can always
              reference it via $main::Request->form from any package.

              > ex.
              >
              > #! /bin/perl
              >
              > package WIZORG;
              > use File::Basename;
              >
              > sub new {
              > my($request) = $main::Request;
              > my($env) = $request->ServerVariables();
              >
              > my $basename = &File::Basename::basename($0);
              > my($title) = join(': ', "WIZORG", $basename);

              Well I like $App->{basename} defined already, but you
              can just as easily do:

              # global.asa
              use File::Basename qw(basename);

              # in script
              <%= &basename($0) %>

              >
              > So... Is it safe to junk it or have I missed a core concept?

              It really starts to help lift reusable code out of
              your ASP scripts, into some central object, so you can
              reuse it better in other places. Having a central
              object can help you from having to define lots of
              other globals to do your dirty work.

              Regards,

              Josh
              ________________________________________________________________
              Josh Chamas, Founder phone:925-552-0128
              Chamas Enterprises Inc. http://www.chamas.com
              NodeWorks Link Checking http://www.nodeworks.com


              ---------------------------------------------------------------------
              To unsubscribe, e-mail: asp-unsubscribe@...
              For additional commands, e-mail: asp-help@...
            • Brat Wizard
              ... When I was working out the logic of all of this- I thought I was on to a universal processing method-- and have code that demonstrates the basic
              Message 6 of 16 , Sep 18, 2002
              View Source
              • 0 Attachment
                > >>Did you know that in the body of an XMLSubs, you can do things
                > >>like <%= $Object->URL %> instead of the __URL__.
                > >
                > > Unless I misunderstand your meaning, I don't think that would do what I
                > > want in this instance since the __TOKENS__ are not being processed until

                When I was working out the logic of all of this- I thought I was on to a
                universal processing method-- and have code that demonstrates the basic
                principles-- but the one thing that kept me stymied was how to handle two
                situations-- the first I'm beginning to figure out a solution for, the second
                I'm still stuck on...

                A) How to pass post-processing formatting information via the XMLSubs
                mechanism w/o getting into really overblown & bizarre syntactical situations
                (I want to keep it as intuitive as possible and like the __TOKEN__ concept as
                its easy to understand and doesn't take up a lot of room).

                The gist of my dilemma is, by way of example, how to declare that a number
                that will be substituted for a token value should have a "%.2f" picture-- or
                some similar issue. In talking all this out I'm starting to develop a
                solution that might work actually (so all of this has actually been helpful
                ;) I'm thinking of creating a token definition tag that would allow inline
                formatting defintions-- perhaps something like:

                <my:sub ...>
                <fmt>COST:%.2f,AGE:%3d,STATE:%uc2</fmt>
                This item costs __COST__ and you must be __AGE__ years old to buy it in the
                state of __STATE__
                </my:sub>

                Then the routine would grab the format pictures in pseudo sprintf format (so
                that additional formatting pictures could be added-- as in %uc2 == 2
                uppercase chars, and apply it as needed when rendering the data...

                Hmm- I think this might work and I already have the bulk of the code to
                support it... aha!!! thanks for listening, I've got some coding to do ;) :)
                :) :) : ) :)

                B) The second issue is harder though and I still haven't thunk up a good
                solution for it yet... and that is how to handle combined or calculated
                post-processed fields-- ie

                <my:sub ...>
                __VAR1__ times __VAR2__ = [product here somehow??]
                </my:sub>

                While this may seem to get a little convoluted, there are some good reasons
                why you would want this-- for example, say you have a flag and you need to
                calculate something one way if it is set and another way if it isn't-- but
                you don't know until after (or during) the post-processing takes place. I
                guess perhaps there is a limit to how much one can cram into this XMLSubs
                thing... ;)

                [..snip..]

                > > Now I have a question for you... ever since I first started programming
                > > ASP projects I have been trying to fathom how to use the "default module"
                > > that goes along with a project??

                > If you have an object that is your Application object, or Model in MVC,
                > then you can abstract things away from your views which are the ASP
                > scripts. The controller is Apache::ASP itself, plus whatever you add to
                > Script_OnStart that might affect how the script gets loaded, if at all!


                Hmm -- what I do now is very close to what you're describing but not taking
                the one last step of pulling the actual application itself into an object
                model. I use the Script_OnStart to instantiate several objects but end up
                passing them around using global vars that I then have to keep up with. If
                I'm understanding you correctly, this is a subtle paradigm shift for me that
                shoves the application out of view and into its own application object class
                which the html files (asp files) within that application domain automagically
                get the benefit of (through instantiation in the Script_OnStart method of the
                global.asa) Which then means that they can access all of the application data
                via the application object, and the various application-level methods again
                via the object (which is not to be confused with the official $Application
                object that is already a part of Apache::ASP). So the details of
                instantiation of the application object are effectively obscured from the
                final html renderer file-- the "view" as it were...

                Thanks for clearing that up. I understand its purpose now. What I've been
                doing hasn't been "wrong" or even ineffective, I just haven't been taking
                full advantage of the one last level of abstraction that's potentially
                available to me. Hmm-- I think I'm going to enjoy exploring this further.


                > Though in breaking of the MVC paradigm, I often also do nice little
                > view shorthands & place them in the app object for the web site like:


                So what you're saying is that _technically_ this would not be the place to put
                (say) html rendering routines, but that _some_ html rendering routines are so
                fundamental and basic, they might as well be in here? For example, you might
                have a counter object where, in purity, you would not want to dictate any
                particular rendering, but because it is used primarily (and almost
                exclusively) as an html adjunct component, you might want to include a
                'renderHtml' (or whatever) method that breaks the paradigm a little...?


                > You don't need to init the object with the $Request->Form
                > data at Script_OnStart however, as you can always
                > reference it via $main::Request->form from any package.

                Yeah, that's how I do it now. Whenever I need form data, I just scoop it up on
                the fly at the beginning of a script. I'm thinking of changing how I do that
                and getting it in the Script_OnStart method and thus already having it
                available. A minor thing.


                > It really starts to help lift reusable code out of
                > your ASP scripts, into some central object, so you can
                > reuse it better in other places. Having a central
                > object can help you from having to define lots of
                > other globals to do your dirty work.

                Yes, in this particular application I'm currently working on, I do pretty
                much-- I've only just gotten to the point where it is enough developed that I
                can start abstracting large chunks of it-- and I've got a good deal of it
                shoved into an object framework now-- not completely though, still have a bit
                more to go.


                Okay, one last (mostly off-topic question) and I'll quit pestering you for
                awhile ;) I am always worried about including too many files in the end
                product. I know that Linux does a good job of file caching-- so after the
                first time, how bad is the hit really? Will subsequent requests get served
                out of memory-- so the time is comparable to a subroutine call (probably not
                quite in any case) or is there still some significant overhead I'm not
                considering that would really make me want to keep the number of includes to
                a minimum. I have been back and forth on this (in my own deliberations) many
                times without a satisfactory answer-- what do you think?


                I like talking to you Josh, you have a wealth of information!

                Thanks for your time and patience.


                John Whitten
                brat@...
                Wizard.Org, Inc.

                --

                --------------------------------------------------------------------------------
                Check out http://www.Wizard.Org for great deals on Electronic Parts
                *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                --------------------------------------------------------------------------------
                ** Affordable Online Store w/Merchant Card Processing & Paypal **
                Write to us: sales@... -- Get your Store Online Today!
                --------------------------------------------------------------------------------



                ---------------------------------------------------------------------
                To unsubscribe, e-mail: asp-unsubscribe@...
                For additional commands, e-mail: asp-help@...
              • Josh Chamas
                ... Assuming that the data is available when the my:sub is starting to get processed, then you can use more XMLSubs to do your dirty work like:
                Message 7 of 16 , Sep 18, 2002
                View Source
                • 0 Attachment
                  > <my:sub ...>
                  > <fmt>COST:%.2f,AGE:%3d,STATE:%uc2</fmt>
                  > This item costs __COST__ and you must be __AGE__ years old to buy it in the
                  > state of __STATE__
                  > </my:sub>
                  >

                  Assuming that the data is available when the my:sub is starting
                  to get processed, then you can use more XMLSubs to do your dirty work like:

                  <% my $data_ref = \%data_hash; %>
                  <my:sub data=$data_ref>
                  <my:value name='COST' fmt='%.2f' />
                  <my:value name='STATE' fmt='%uc2' />
                  </my:sub>

                  That is at least how I would try to do it.

                  If you can end up with your document written entirely in XML,
                  then you are on your way to having your data written entirely
                  separately from your style, which is a good goal. This is
                  the XML/XSLT paradigm, but can be implemented with XHTML,
                  XMLSubs, XSLT, you pick your favorite.

                  > B) The second issue is harder though and I still haven't thunk up a good
                  > solution for it yet... and that is how to handle combined or calculated
                  > post-processed fields-- ie
                  >
                  > <my:sub ...>
                  > __VAR1__ times __VAR2__ = [product here somehow??]
                  > </my:sub>
                  >

                  Be careful... you are creating your own mini language here.
                  You could do this instead:

                  <% my $data_ref = \%$data_hash; %>
                  <my:sub>
                  <%= $data_ref->{VAR1} * $data_ref->{VAR2} %>
                  </my:sub>

                  I caution against going down the create your own mini language
                  path because it will end up being a language that only you know.
                  I would recommend more that if you want to inline a mini language,
                  that you look into rendering inline a bit of a template toolkit
                  or HTML::Template into your Apache::ASP, so you might have:

                  <my:tt data=$data>
                  Template Toolkit mini language processed here
                  You could then init the template with $data for parameters
                  </my:tt>

                  At least TT or HTML::Template are already widely used, and would
                  suggest you go down that path for extending your Apache::ASP framework.

                  > While this may seem to get a little convoluted, there are some good reasons
                  > why you would want this-- for example, say you have a flag and you need to
                  > calculate something one way if it is set and another way if it isn't-- but
                  > you don't know until after (or during) the post-processing takes place. I
                  > guess perhaps there is a limit to how much one can cram into this XMLSubs
                  > thing... ;)

                  There is a limit, but I would like to break it. I believe I can add
                  a lot of power to XMLSubs, if I allow them to also be called at
                  compile time as an extension, so that the ASP template being compiled
                  could be modified instead of the output. The runtime model has more
                  limits, and the compile time model would only be added as an extension.
                  I have been mulling these kinds of extensions to XMLSubs for a while,
                  so do not hold your breath.

                  >
                  > Hmm -- what I do now is very close to what you're describing but not taking
                  > the one last step of pulling the actual application itself into an object
                  > model. I use the Script_OnStart to instantiate several objects but end up
                  > passing them around using global vars that I then have to keep up with. If
                  > I'm understanding you correctly, this is a subtle paradigm shift for me that
                  > shoves the application out of view and into its own application object class
                  > which the html files (asp files) within that application domain automagically
                  > get the benefit of (through instantiation in the Script_OnStart method of the
                  > global.asa) Which then means that they can access all of the application data
                  > via the application object, and the various application-level methods again
                  > via the object (which is not to be confused with the official $Application
                  > object that is already a part of Apache::ASP). So the details of
                  > instantiation of the application object are effectively obscured from the
                  > final html renderer file-- the "view" as it were...
                  >

                  Yep.

                  > Thanks for clearing that up. I understand its purpose now. What I've been
                  > doing hasn't been "wrong" or even ineffective, I just haven't been taking
                  > full advantage of the one last level of abstraction that's potentially
                  > available to me. Hmm-- I think I'm going to enjoy exploring this further.
                  >

                  Right. The more you get into this stuff, the more effective you become.
                  Its pretty neat because you can constantly learn how to do things better.
                  I do all the time, even with Apache::ASP. :)

                  >
                  > So what you're saying is that _technically_ this would not be the place to put
                  > (say) html rendering routines, but that _some_ html rendering routines are so
                  > fundamental and basic, they might as well be in here? For example, you might
                  > have a counter object where, in purity, you would not want to dictate any
                  > particular rendering, but because it is used primarily (and almost
                  > exclusively) as an html adjunct component, you might want to include a
                  > 'renderHtml' (or whatever) method that breaks the paradigm a little...?
                  >

                  Right. Technically, I think you need to have view objects doing
                  view things specific to the rendering platform ( HTML ), separate
                  from the model/App object. Theoretically the App object should be just
                  as useful in a Tk GUI view renderer as it is with an HTML renderer.

                  >
                  > Okay, one last (mostly off-topic question) and I'll quit pestering you for
                  > awhile ;) I am always worried about including too many files in the end
                  > product. I know that Linux does a good job of file caching-- so after the
                  > first time, how bad is the hit really? Will subsequent requests get served
                  > out of memory-- so the time is comparable to a subroutine call (probably not
                  > quite in any case) or is there still some significant overhead I'm not
                  > considering that would really make me want to keep the number of includes to
                  > a minimum. I have been back and forth on this (in my own deliberations) many
                  > times without a satisfactory answer-- what do you think?
                  >

                  The linux file cache is really efficient, so include away. The virtues
                  of component decomposition & reusability far outweigh any performance
                  penalty your site may suffer. Computers get faster, but people don't,
                  so code maintainability is of greater importance, especially when
                  the performance hit is small.

                  If you really want your site to be fast, then precompile your scripts
                  in the parent httpd. The real performance hit your are saving yourself
                  from it having to compile the scripts in every child httpd separately.
                  Read here for more:

                  http://www.apache-asp.org/tuning.html#Precompile%20S36827838

                  Regards,

                  Josh

                  ________________________________________________________________
                  Josh Chamas, Founder phone:925-552-0128
                  Chamas Enterprises Inc. http://www.chamas.com
                  NodeWorks Link Checking http://www.nodeworks.com


                  ---------------------------------------------------------------------
                  To unsubscribe, e-mail: asp-unsubscribe@...
                  For additional commands, e-mail: asp-help@...
                • Brat Wizard
                  ... I ve been playing around with this some more and have this observation to make (among some others)-- what you have started here with XMLSubs is very nifty
                  Message 8 of 16 , Sep 19, 2002
                  View Source
                  • 0 Attachment
                    On Wednesday 18 September 2002 01:10 pm, Josh Chamas spewed into the ether:
                    > Assuming that the data is available when the my:sub is starting
                    > to get processed, then you can use more XMLSubs to do your dirty work like:
                    >
                    > <% my $data_ref = \%data_hash; %>
                    > <my:sub data=$data_ref>
                    > <my:value name='COST' fmt='%.2f' />
                    > <my:value name='STATE' fmt='%uc2' />
                    > </my:sub>

                    I've been playing around with this some more and have this observation to make
                    (among some others)-- what you have started here with XMLSubs is very nifty
                    and offers the designer a large degree of abstraction ability (a la
                    templating) in crufting up pages-- however, the one big weakness that I see
                    is that all of of the ASP assisted bits-- nested subs, <% %> substitution,
                    etc-- all happen in the PRE processing stage and not DURING the processing
                    stage. A lot of what one wants to do doesn't come into scope until _during_
                    the processing.

                    For example, one use of this ability (and enabling a big win) would be in
                    interpreting/rendering row data selected from a database. None of the nifty
                    ASP-assist functions are at all useful in this context because it isn't until
                    inside the iteration loop which is inside the my:sub function that this
                    information first becomes available.

                    Here is an (actual) example of the problem:

                    <table width="100%">
                    <my:pgloop sth=$sth>
                    <fmt>PRICE:%.2f</fmt>
                    <tr>
                    <td><my:pimage pg="__PG__" sku="__SKU__" width="32"/></td>
                    <td><a href="catalog/__PG__/__SKU__">__SKU__</a></td>
                    <td>__USER1__</td>
                    <td>__NAME__</td>
                    <td align=right>__QTY_ONHAND__</td>
                    <td align=right>__AMT_PRICE__</td>
                    </tr>
                    </my:pgloop>
                    </table>

                    In this case, the 'my:pimage' sub is nested inside the 'my:pgloop' sub-- the
                    statement handle '$sth' contains the selected DBI table rows, and the pgloop
                    sub iterates the rows and subs the template for each row. The 'my:pimage' sub
                    retrieves an image based on the product group and sku id. But in this case,
                    the sku is not known until inside the pg:loop func. Intuitively (to me at
                    least) the above is the logical way (and perhaps the only way) to construct
                    the template. However, in real life, when I do this, ASP attempts to resolve
                    the my:pimage sub before handing it off to the my:pgloop sub-- which is
                    before any token-data is available to resolve the __TOKENS__. So processing
                    (as written) works from the inside-out instead of outside-in, which imo would
                    be the more intuitive and useful approach.

                    There might also be a compromise approach that's possible too- so that <% %>
                    substitutions happen immediately before the sub, while __TOKEN__ values and
                    nested xmlsubs would be processed after (during) being passed (ie. be delayed
                    in resolution by one level of nesting so that any external references ie.
                    __TOKENS__ or whatever could get resolved first).


                    > If you can end up with your document written entirely in XML,
                    > then you are on your way to having your data written entirely
                    > separately from your style, which is a good goal. This is
                    > the XML/XSLT paradigm, but can be implemented with XHTML,
                    XMLSubs, XSLT, you pick your favorite.

                    Yes, I'm doing my best to push my application in that direction. My current
                    app involves an e-commerce platform which has to support a wide variety of
                    styles and configurations. I am hoping to get to the point where the customer
                    can supply the basic page with all the business logic accessible via special
                    tags. So they get the control over design and layout while maintaining (but
                    not being responsible for) the actual workings of the system.


                    > > B) The second issue is harder though and I still haven't thunk up a good
                    > > solution for it yet... and that is how to handle combined or calculated
                    > > post-processed fields-- ie
                    > >
                    > > <my:sub ...>
                    > > __VAR1__ times __VAR2__ = [product here somehow??]
                    > > </my:sub>
                    >
                    > Be careful... you are creating your own mini language here.

                    Heh- I hope not. I'm trying to stay away from that on purpose. But what I am
                    discovering is that there needs to be formatting information, and also I had
                    another idea before I went to sleep last night-- and that was the idea of
                    tying a token to a well-known (somewhere-else predefined) rendering style...

                    <my:sub>
                    <type>USER_TYPE:userlookup</type>
                    </my:sub>

                    And 'userlookup' would be a specific reference (either implicit or
                    interpreted) to a renderer-- meaning it would tie the USER_TYPE token/data
                    pair to a bit of code (function/whatever) that would render it in a way
                    appropriate to a user lookup function-- however that happens to be defined.

                    A couple of years ago, I was working on a different (non-ASP) app where I
                    needed to display a list of "who's on" along with related information about
                    the user, where they were from, what they were doing, the time, and
                    idle-time, and other information. In addition, there were several _very_
                    similar variations on this theme depending on who was asking, why they were
                    asking, and what the general gist of the question was-- after writing a bunch
                    of who's-on scripts, all slighly different but basically the same, I decided
                    to create a more flexible approach and designed a single who's-on system that
                    allowed predefined "fields", "renderers", and "reports" (stored in config
                    files) that defined what a field was (where it came from, how it was used,
                    etc) and this allowed me to create artificial fields through some transform
                    of existing fields, and defined renderers that could be tied to a particular
                    field (in the field definition), and finally reports which were collections
                    of fields and rules regarding who could access the report and meta
                    information such as report title and other "pretty" information.

                    When I first started, it seemed pretty daunting. But in the end, it turned out
                    that it was an extremely workable system-- there were a few wrinkles that
                    needed to be ironed-out and areas extended in order to ultimately make it all
                    work the way it should. The code was easy to follow and most importantly made
                    designing a new report a 10-minute process. Once the first few reports had
                    been created, 99% of the field & renderers had already been defined so
                    building a new report consisted mostly of choosing predefined fields and the
                    context in which the report could be viewed.

                    While that bit of code was specific to the application I was working on at the
                    time, the _idea_ of that code seems germain and relevant to what we're
                    discussing here-- and is very similar to this whole templating thing we're
                    talking about.



                    Another useful thing might be a <def> field (define) field that could
                    construct artificial tokens based on expression-manipulation of existing data
                    available in the dataset at time of rendering. That way you could have a cost
                    field and apply a markup value to it and come up with an artificial, but
                    usable price token.

                    <my:sub>
                    <define>PRICE:COST*1.2</define>
                    The cost of this item is __COST__ and it is currently selling for __PRICE__.
                    </my:sub>

                    Finally there is a need for some sort of simple if/then logic. This is where
                    everything gets tricky. If you go to far with this concept then you cross the
                    threshold of simple formatting and get into procedural aspects which should
                    probably be avoided. There probably should never be any sort of iterative
                    aspect. That seems definately over the line, and can be handled anyway by
                    simply creating a my:sub that performs the iteration. But consider this
                    situation:

                    Suppose you have a product table and some of the products in the table are on
                    sale. When you retrieve the list of the items, you would like to apply one
                    style if onsale, and another if not.

                    I think there oughta be some sort of facility for handling this type of
                    formatting situation at least for the simplistic case-- though I quickly
                    admit that if you add too much flexibility that it gets out of hand very
                    quickly, and further I am at a loss to suggest a suitable style for such a
                    framework.

                    Besides, at some point, if you alter enough of the basic template, you're not
                    really saving yourself any work, which was the original objective, and
                    arguably could be adding to your workload by adding additional crap to
                    remember.



                    > You could do this instead:
                    >
                    > <% my $data_ref = \%$data_hash; %>
                    > <my:sub>
                    > <%= $data_ref->{VAR1} * $data_ref->{VAR2} %>
                    > </my:sub>
                    >
                    > I caution against going down the create your own mini language
                    > path because it will end up being a language that only you know.

                    Definatelyt agreed. Trying to stick to formatting issues only.



                    > I would recommend more that if you want to inline a mini language,
                    > that you look into rendering inline a bit of a template toolkit
                    > or HTML::Template into your Apache::ASP

                    Actually I have looked at them and they seem overblown and needlessly
                    cumbersome for what I want to do. I think you could get away with some very
                    simple formatting rules, and perhaps some method to generate artificial
                    tokens. Being able to define a renderer is a nice thing too but an extra. All
                    of these things are issues the designer/webmaster needs to have access to in
                    order to have the control over the creative aspect of the site. They do not
                    need to concern themselves with the inner workings of the XMLSubs they use.
                    They need only know that if you supply "these parameters" and in "this way"
                    then "this will happen"-- very black box-ish, and html-like.


                    >> I guess perhaps there is a limit to how much one can cram
                    >> into this XMLSubs thing... ;)
                    >
                    > There is a limit, but I would like to break it. I believe I can add
                    > a lot of power to XMLSubs, if I allow them to also be called at
                    > compile time as an extension, so that the ASP template being compiled
                    > could be modified instead of the output. The runtime model has more
                    > limits, and the compile time model would only be added as an extension.
                    > I have been mulling these kinds of extensions to XMLSubs for a while,
                    > so do not hold your breath.

                    I don't hold my breath much anymore. I tend to faint a lot that way ;)


                    > If you really want your site to be fast, then precompile your scripts
                    > in the parent httpd. The real performance hit your are saving yourself
                    > from it having to compile the scripts in every child httpd separately.
                    > Read here for more:
                    >
                    > http://www.apache-asp.org/tuning.html#Precompile%20S36827838

                    Yup, I already do that and it works well. Also moving the .htaccess stuff into
                    the apache config helps a lot too.


                    BTW- here is a better and improved version of the rendering function I
                    submitted last time. It is more efficient because it cranks through the
                    tokens it finds instead of all the ones available in the hash. The render
                    function itself though is a drop-in replacement of the one I presented
                    before. This snippet is capable of processing the my:sub examples I presented
                    above (though you would have to finish wrapping the my:sub setup around it).


                    my %fmt = (); # for format view

                    ## extract format (if any) - what's left becomes template string
                    $body =~ s/<fmt>(.*?)<\/fmt>//i;
                    $fmt = $1;

                    ## scoop-up formats into a convenient hash
                    foreach (split(/,/, $fmt)) {
                    my ($key, $val) = split(/:/, $_);
                    $fmt{uc(eatwhite($key))} = eatwhite($val);
                    }

                    foreach (@hash_list) { render($body, $_, \%fmt) }

                    ## more efficient render func
                    sub render {
                    my ($tmpl, $hash, $fmt) = @_;
                    while ($tmpl =~ /__(.*?)__/) {
                    my $TOKEN = $1; my $token = lc($TOKEN);
                    if ((my $fmt = $$fmt{$TOKEN}) ne undef) {
                    # to-uppercase
                    if ($fmt =~ /^%uc/i) { $fmt =~ s/[^0-9]//gm;
                    $$hash{$token} = uc(substr($$hash{$token}, 0, $fmt ||
                    length($$hash{$token}))); }
                    # to-lowercase
                    elsif ($fmt =~ /^%lc/i) { $fmt =~ s/[^0-9]//gm;
                    $$hash{$token} = lc(substr($$hash{$token}, 0, $fmt ||
                    length($$hash{$token}))); }
                    # picture
                    else { $$hash{$token} = sprintf($fmt, $$hash{$token});
                    }
                    }
                    $tmpl =~ s/__${TOKEN}__/$$hash{$token}/gme;
                    }
                    print $tmpl;
                    }


                    __END__

                    BTW-- additional predefined formats can be added as desired. Some useful ones
                    to add might include a telephone-number style renderer, a ssn style, a
                    zipcode style (zip+4), an email style, a url style, etc. They could all be
                    added in the if/then ladder where it is deciding what format to apply to the
                    data. Also, if enough renderers are defined, or additional
                    functionality/flexibility/or config options is desired, the whole formatting
                    bit can be removed to its own subsystem in a style similar to the "who's-on"
                    model I described above.


                    Here is a snippet of code from an actual my:sub (my:pgloop, used above) that
                    makes use of this particular renderer:

                    sub my::pgloop { # iterate thru results set and process body block
                    my ($args, $body) = @_;

                    ## extract format (if any) - what's left becomes template string
                    my %fmt = (); # hash for format view
                    $body =~ s/<fmt>(.*?)<\/fmt>//i;
                    my $fmt = $1;

                    ## scoop-up formats into a convenient hash
                    foreach (split(/,/, $fmt)) {
                    my ($key, $val) = split(/:/, $_);
                    $fmt{uc(eatwhite($key))} = eatwhite($val);
                    }

                    ## iterate data rows and render accordingly
                    while (my $row = $$args{sth}->fetchrow_hashref('NAME_lc')) {
                    ## render hash using template string and format hash
                    render($body, $row, \%fmt);
                    }
                    }

                    __END__

                    This illustrates how a complete XMLSub function can be constructed using the
                    snippets of code I've presented thus far. Simply substitute the guts of this
                    function with the code snippets and make the minor adjustments so that the
                    variables match up.


                    Finally I would like to present another snippet of code that I use in my
                    applications. This time it is an embeddable search form that makes it very
                    easy to stick a search widget just about anywhere.

                    sub my::search { # display a small, embeddable search form
                    my ($args, $body) = @_;
                    my $script = $$args{script} || 'catalog';
                    my $class = qq{class="$$args{class}"} if ($$args{class} ne '');
                    my $caption = qq{<td align=right $class>$body</td>} if ($body ne '');
                    my $size = $$args{size} || 10;
                    my $go_button = ($$args{go_button} ne '')?qq{ <input type=image
                    src
                    ="$$args{go_button}" border=0>}:qq{  <input type=submit value="Go">};
                    print << "EOF";
                    <table border=0 cellpadding=1 cellspacing=0>
                    <form method=GET action="/$storeid/$script">
                    <tr>
                    $caption
                    <td $class>
                     <input type="text" name="search" value="-Search-" size=$size
                    maxle
                    ngth=80 onfocus="if(this.value=='-Search-') {this.value='';}"
                    onblur="if(this.va
                    lue=='') {this.value='-Search-';}">
                    $go_button
                    </font>
                    </td>
                    </tr>
                    </form>
                    </table>
                    EOF
                    }

                    __END__

                    To use this in an html/asp script, just do something like:

                    <my:search go_button="$themeurl/go_button.gif"/>

                    -or-

                    <my:search go_button="$themeurl/go_button.gif"><b>Search</b></my:search>

                    (Anything placed inside the tags becomes the caption for the search). Notice
                    also that this includes some simple javascript to make the word 'search'
                    appear inside the text box whenever the user has not typed anything in it.
                    This makes it possible to use it in a very "small" footprint.


                    As always, I hope I'm helping someone. There's a lot of neat stuff you can do
                    with Apache::ASP. Part of getting it widely-used is helping people to see how
                    it can be used to solve real-world problems and offering real world examples
                    to "steal" or get inspired by.



                    John


                    --------------------------------------------------------------------------------
                    Check out http://www.Wizard.Org for great deals on Electronic Parts
                    *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                    --------------------------------------------------------------------------------
                    ** Affordable Online Store w/Merchant Card Processing & Paypal **
                    Write to us: sales@... -- Get your Store Online Today!
                    --------------------------------------------------------------------------------



                    ---------------------------------------------------------------------
                    To unsubscribe, e-mail: asp-unsubscribe@...
                    For additional commands, e-mail: asp-help@...
                  • Brat Wizard
                    ... Ta-Da! Here is the nifty solution... By slightly changing the template-- notice the my:pimage xmlsub now has a different format using __[ ... ]__ to
                    Message 9 of 16 , Sep 20, 2002
                    View Source
                    • 0 Attachment
                      > Here is an (actual) example of the problem:
                      >
                      > <table width="100%">
                      > <my:pgloop sth=$sth>
                      > <fmt>PRICE:%.2f</fmt>
                      > <tr>
                      > <td><my:pimage pg="__PG__" sku="__SKU__" width="32"/></td>
                      > <td><a href="catalog/__PG__/__SKU__">__SKU__</a></td>
                      > <td>__USER1__</td>
                      > <td>__NAME__</td>
                      > <td align=right>__QTY_ONHAND__</td>
                      > <td align=right>__AMT_PRICE__</td>
                      > </tr>
                      > </my:pgloop>
                      > </table>


                      Ta-Da! Here is the nifty solution... By slightly changing the template--
                      notice the 'my:pimage' xmlsub now has a different format using __[ ... ]__ to
                      distinguish it instead (and the syntax is consistent with the __TOKEN__
                      style). This keeps it from getting processed before it gets passed to the
                      first xmlsub (my:pgloop).
                      Then, in the render() func, add one more statement to change the __[ ]__
                      nomenclature back to < > and then pass it through $Response->Include()
                      instead of printing it directly. This has the effect of substituting the
                      parameters, fixing up the embedded xmlsubs, and then re-processing everything
                      with the now-current data. By using $Response->Include to do it, the now
                      correct xmlsubs will get processed with the substituted data.

                      <table width="100%">
                      <my:pgloop sth=$sth>
                      <fmt>PRICE:%.2f</fmt>
                      <tr>
                      <td>__[my:pimage pg="__PG__" sku="__SKU__" width="32"/]__</td>
                      <td><a href="catalog/__PG__/__SKU__"><u>__SKU__</u></a></td>
                      <td>__USER1__</td>
                      <td>__NAME__</td>
                      <td align=right>__QTY_ONHAND__</td>
                      <td align=right>__AMT_PRICE__</td>
                      </tr>
                      </my:pgloop>
                      </table>


                      The completed render() function looks like this:

                      sub render { ## process a body-template string and render appropriately
                      my ($tmpl, $hash, $fmt) = @_;
                      $tmpl =~ s/__\[(.*?)\]__/<$1>/gm; # fixup delayed-embedded xmlsubs
                      while ($tmpl =~ /__(.*?)__/) {
                      my $TOKEN = $1; my $token = lc($TOKEN);
                      if ((my $fmt = $$fmt{$TOKEN}) ne undef) {
                      # to-uppercase
                      if ($fmt =~ /^%uc/i) { $fmt =~ s/[^0-9]//gm;
                      $$hash{$token} = uc(substr($$hash{$token}, 0, $fmt ||
                      length($$hash{$token}))); }
                      # to-lowercase
                      elsif ($fmt =~ /^%lc/i) { $fmt =~ s/[^0-9]//gm;
                      $$hash{$token} = lc(substr($$hash{$token}, 0, $fmt ||
                      length($$hash{$token}))); }
                      # picture
                      else { $$hash{$token} = sprintf($fmt, $$hash{$token});
                      }
                      }
                      $tmpl =~ s/__${TOKEN}__/$$hash{$token}/gme;
                      }
                      $Response->Include(\$tmpl);
                      }

                      __END__



                      --------------------------------------------------------------------------------
                      Check out http://www.Wizard.Org for great deals on Electronic Parts
                      *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                      --------------------------------------------------------------------------------
                      ** Affordable Online Store w/Merchant Card Processing & Paypal **
                      Write to us: sales@... -- Get your Store Online Today!
                      --------------------------------------------------------------------------------



                      ---------------------------------------------------------------------
                      To unsubscribe, e-mail: asp-unsubscribe@...
                      For additional commands, e-mail: asp-help@...
                    • Josh Chamas
                      ... Right, its almost as if one would want a pre-processing stage of not the output, but of the content. The current model was not built to be easily
                      Message 10 of 16 , Sep 20, 2002
                      View Source
                      • 0 Attachment
                        Brat Wizard wrote:
                        > On Wednesday 18 September 2002 01:10 pm, Josh Chamas spewed into the ether:
                        >
                        >>Assuming that the data is available when the my:sub is starting
                        >>to get processed, then you can use more XMLSubs to do your dirty work like:
                        >>
                        >><% my $data_ref = \%data_hash; %>
                        >><my:sub data=$data_ref>
                        >> <my:value name='COST' fmt='%.2f' />
                        >> <my:value name='STATE' fmt='%uc2' />
                        >></my:sub>
                        >
                        >
                        > I've been playing around with this some more and have this observation to make
                        > (among some others)-- what you have started here with XMLSubs is very nifty
                        > and offers the designer a large degree of abstraction ability (a la
                        > templating) in crufting up pages-- however, the one big weakness that I see
                        > is that all of of the ASP assisted bits-- nested subs, <% %> substitution,
                        > etc-- all happen in the PRE processing stage and not DURING the processing
                        > stage. A lot of what one wants to do doesn't come into scope until _during_
                        > the processing.

                        Right, its almost as if one would want a pre-processing stage of not the
                        output, but of the content. The current model was not built to be easily
                        extendable to this as there is only one sub per XMLSubs that gets called,
                        but what you would really want is something like:

                        sub my::sub_pre()
                        sub my::sub_post()

                        Unfortunately, any parsing of this script is quite likely to thrown lines
                        numbers off from the original source.

                        Another mechanism for might be good to use for this is to use ASPish
                        global.asa events that can be called every XMLSubs execution, both
                        before & after, like:

                        sub XMLSubs_OnStart {
                        my($xml_tag_name, $args, $html_input) = @_;
                        }

                        sub XMLSubs_OnEnd {
                        my($xml_tag_name, $args, $html_output) = @_;
                        }

                        The problem that I see with this is that it makes your XMLSubs
                        necessarily wired to the application, when ideally it should
                        be easily repurposable to other web applications. JSP taglibs
                        seem to solve this problem by having an XML description file
                        for each tag lib.

                        I think I would like to solve this by having the ability to
                        map a module namespace to an XML namespace, and then have
                        a certain OO specification that if the module implements
                        it, then the XMLSubs can have its preprocessing stage et al.

                        >
                        > For example, one use of this ability (and enabling a big win) would be in
                        > interpreting/rendering row data selected from a database. None of the nifty
                        > ASP-assist functions are at all useful in this context because it isn't until
                        > inside the iteration loop which is inside the my:sub function that this
                        > information first becomes available.
                        >
                        > Here is an (actual) example of the problem:
                        >
                        > <table width="100%">
                        > <my:pgloop sth=$sth>
                        > <fmt>PRICE:%.2f</fmt>
                        > <tr>
                        > <td><my:pimage pg="__PG__" sku="__SKU__" width="32"/></td>
                        > <td><a href="catalog/__PG__/__SKU__">__SKU__</a></td>
                        > <td>__USER1__</td>
                        > <td>__NAME__</td>
                        > <td align=right>__QTY_ONHAND__</td>
                        > <td align=right>__AMT_PRICE__</td>
                        > </tr>
                        > </my:pgloop>
                        > </table>
                        >
                        > In this case, the 'my:pimage' sub is nested inside the 'my:pgloop' sub-- the
                        > statement handle '$sth' contains the selected DBI table rows, and the pgloop
                        > sub iterates the rows and subs the template for each row. The 'my:pimage' sub
                        > retrieves an image based on the product group and sku id. But in this case,
                        > the sku is not known until inside the pg:loop func. Intuitively (to me at

                        In an OO model, I think we could achieve something like this as in:

                        my $pgloop = My::Pgloop->new(
                        ASP => $asp,
                        Attrib => { sth => $sth },
                        Content => \$data_within,
                        };
                        my $pgimage = My::PgImage->new(
                        ASP => $asp,
                        Attrib => { pg=>"__PG__" sku=>"__SKU__" },
                        Parent => $pgloop
                        };
                        $pgimage->execute(\'');
                        $pgloop->execute(\$final_data_output_within);

                        This pre/post processing model would allow pgimage to
                        work with $self->{Parent}{sth}, or pgloop could populate
                        its own data in this way. Output from pgimage could be
                        trapped and inlined, passed into the execute() function
                        for pgloop.

                        Now, I'm not saying I could deliver on all of this necessarily,
                        but this seems like where the model should go, or some such
                        directtion.

                        > Another useful thing might be a <def> field (define) field that could
                        > construct artificial tokens based on expression-manipulation of existing data
                        > available in the dataset at time of rendering. That way you could have a cost
                        > field and apply a markup value to it and come up with an artificial, but
                        > usable price token.
                        >
                        > <my:sub>
                        > <define>PRICE:COST*1.2</define>
                        > The cost of this item is __COST__ and it is currently selling for __PRICE__.
                        > </my:sub>
                        >

                        If we have a preprocessing stage like above, then you could probably
                        take the inner content and read through it with XML::Simple, or HTML::Parser
                        and pick out your internal definitions that way. It may be that I am unable
                        to achieve a fully post processed model where I can trap the output of
                        the inner tokens too, so that we would need to put the rest of the
                        data into another tag that you could read easily as well at input time like:

                        <my:sub>
                        <define>PRICE:COST*1.2</define>
                        <output>The cost of this item is __COST__ and it is currently selling for __PRICE__.</output>
                        </my:sub>

                        This kind of tag could probably be entirely handled by My::Sub->new() without
                        the need for a post process stage.

                        > Finally there is a need for some sort of simple if/then logic. This is where
                        > everything gets tricky. If you go to far with this concept then you cross the
                        > threshold of simple formatting and get into procedural aspects which should
                        > probably be avoided. There probably should never be any sort of iterative
                        > aspect. That seems definately over the line, and can be handled anyway by
                        > simply creating a my:sub that performs the iteration. But consider this
                        > situation:

                        In a pre-process model, the if/else children could be evaluated by the
                        parent at parent->new() time, or could look at the parent data at their
                        if->new() time. If ASP <% if() { } %> will still be supported, within,
                        then that could be evaluated at parent->new() time by simply doing:

                        $output = $Response->TrapInclude(\$content);

                        where that will execute the content without needing a post processing model
                        at all. Hmmm, I kind of like where this is going. :) Of course its totally
                        different that what we have today.

                        > sub render {
                        > my ($tmpl, $hash, $fmt) = @_;
                        > while ($tmpl =~ /__(.*?)__/) {
                        > my $TOKEN = $1; my $token = lc($TOKEN);
                        > if ((my $fmt = $$fmt{$TOKEN}) ne undef) {
                        > # to-uppercase

                        Seeing where you are going with this, I feel like an object per
                        XMLSubs approach has the greatest potential. With well well
                        defined reserved interface, mixed in with Apache::ASP::Share
                        system templates, I think this can go a long way towards
                        building reusable components.

                        > ="$$args{go_button}" border=0>}:qq{  <input type=submit value="Go">};
                        > print << "EOF";
                        > <table border=0 cellpadding=1 cellspacing=0>
                        > <form method=GET action="/$storeid/$script">
                        > <tr>
                        > $caption

                        I am hoping that this form processing could be done from a
                        reusable XMlSubs by something like $ASP->Response->Include('Share::My/Subs/form.inc');
                        I believe the way I constructed the Share:: mechanism is that
                        some could overload that template at their $GLOBAL/My/Subs/form.inc
                        to further customize what you have done, but there is a whole
                        lot of extension that can be done there too to make it really powerful.

                        Regards,

                        Josh
                        ________________________________________________________________
                        Josh Chamas, Founder phone:925-552-0128
                        Chamas Enterprises Inc. http://www.chamas.com
                        NodeWorks Link Checking http://www.nodeworks.com


                        ---------------------------------------------------------------------
                        To unsubscribe, e-mail: asp-unsubscribe@...
                        For additional commands, e-mail: asp-help@...
                      • Josh Chamas
                        ... Now that is interesting. You grabbed all the raw output, preprocessed it, and then ran executed it again, effectively creating a preprocessing model.
                        Message 11 of 16 , Sep 20, 2002
                        View Source
                        • 0 Attachment
                          Brat Wizard wrote:

                          > # picture
                          > else { $$hash{$token} = sprintf($fmt, $$hash{$token});
                          > }
                          > }
                          > $tmpl =~ s/__${TOKEN}__/$$hash{$token}/gme;
                          > }
                          > $Response->Include(\$tmpl);
                          > }
                          >

                          Now that is interesting. You grabbed all the raw output, preprocessed
                          it, and then ran executed it again, effectively creating a preprocessing
                          model. Tricky. This gives something to think about...

                          --Josh
                          ________________________________________________________________
                          Josh Chamas, Founder phone:925-552-0128
                          Chamas Enterprises Inc. http://www.chamas.com
                          NodeWorks Link Checking http://www.nodeworks.com


                          ---------------------------------------------------------------------
                          To unsubscribe, e-mail: asp-unsubscribe@...
                          For additional commands, e-mail: asp-help@...
                        • Brat Wizard
                          Yes, but extrordinarily easy-to-do and it didn t break nuthin ;) ... -- ... Check out http://www.Wizard.Org for great deals on Electronic Parts *NEW* Computer
                          Message 12 of 16 , Sep 20, 2002
                          View Source
                          • 0 Attachment
                            Yes, but extrordinarily easy-to-do and it didn't break nuthin ;)


                            On Friday 20 September 2002 02:27 pm, you muttered:
                            > Brat Wizard wrote:
                            > > # picture
                            > > else { $$hash{$token} = sprintf($fmt,
                            > > $$hash{$token}); }
                            > > }
                            > > $tmpl =~ s/__${TOKEN}__/$$hash{$token}/gme;
                            > > }
                            > > $Response->Include(\$tmpl);
                            > > }
                            >
                            > Now that is interesting. You grabbed all the raw output, preprocessed
                            > it, and then ran executed it again, effectively creating a preprocessing
                            > model. Tricky. This gives something to think about...
                            >
                            > --Josh
                            > ________________________________________________________________
                            > Josh Chamas, Founder phone:925-552-0128
                            > Chamas Enterprises Inc. http://www.chamas.com
                            > NodeWorks Link Checking http://www.nodeworks.com

                            --

                            --------------------------------------------------------------------------------
                            Check out http://www.Wizard.Org for great deals on Electronic Parts
                            *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                            --------------------------------------------------------------------------------
                            ** Affordable Online Store w/Merchant Card Processing & Paypal **
                            Write to us: sales@... -- Get your Store Online Today!
                            --------------------------------------------------------------------------------



                            ---------------------------------------------------------------------
                            To unsubscribe, e-mail: asp-unsubscribe@...
                            For additional commands, e-mail: asp-help@...
                          • Brat Wizard
                            ... Josh- why not make it a simple directive, like a pragma-- then it could be specified inline by the end-user whenever (and if-ever) they need it one way or
                            Message 13 of 16 , Sep 20, 2002
                            View Source
                            • 0 Attachment
                              > Right, its almost as if one would want a pre-processing stage of not the
                              > output, but of the content. The current model was not built to be easily
                              > extendable to this as there is only one sub per XMLSubs that gets called,
                              > but what you would really want is something like:
                              >
                              > sub my::sub_pre()
                              > sub my::sub_post()

                              Josh- why not make it a simple directive, like a pragma-- then it could be
                              specified inline by the end-user whenever (and if-ever) they need it one way
                              or the other.

                              Perhaps something like:

                              $Apache::ASP::XMLSubsPostProc = 1

                              (or whatever)

                              And that would indicate to the system that it should enter post-processing
                              mode. That way you would stay compatible with current code but allow the
                              ability to be turned on/off as/if needed.

                              However, in thinking it through-- generally-speaking (while maybe not true in
                              every case, for most cases it would be)-- things that would get substituted a
                              la <% %> prior to calling the first my:sub are still available to be
                              substituted afterwards as long as you get back to the original scope-context.
                              I'm trying to think of a situation where it would be disadvantageous to delay
                              substitution... nothing springs to mind right off but I don't want to say
                              never either.

                              So if you had, say:

                              <my:sub>
                              <my:nestedsub><%=$blech%> __TOKEN1__</my:nestedsub>
                              <%=$foobar%> __TOKEN2__
                              </my:sub>

                              You could wait until after the first my:sub had been called to interpret the
                              rest-- just process everything post. In my thinking __TOKEN1__ and __TOKEN2__
                              would get resolved by the renderer function on the first pass and
                              <my:nestedsub>, $blech, and $foobar, would get processed immediately
                              afterwards-- after the tokens had been substituted.

                              How would that work out do you think?


                              > Unfortunately, any parsing of this script is quite likely to thrown lines
                              > numbers off from the original source.

                              Yeah well, life sucks don't it ;)

                              If it really bothered you, you could always make a note in the output that the
                              line numbering might be off.


                              > Another mechanism for might be good to use for this is to use ASPish
                              > global.asa events that can be called every XMLSubs execution, both
                              > before & after, like:
                              >
                              > sub XMLSubs_OnStart {
                              > my($xml_tag_name, $args, $html_input) = @_;
                              > }
                              >
                              > sub XMLSubs_OnEnd {
                              > my($xml_tag_name, $args, $html_output) = @_;
                              > }

                              This doesn't seem like a very clean solution to me, a kludge at best. If you
                              don't mind my saying so, I think my solution is better using the rendering
                              function I put forth. Its also easier and works out-of-the-box with no
                              additional modification.

                              Just delay the <% %> substitution until after the initial rendering stage and
                              let post-processing pick it up-- the only minor hitch is that you need to
                              make sure you're back in the original scope before doing the substitution.
                              __TOKENS__ get replaced inside the my:sub function, by the my:sub function--
                              whether with the render function or directly by the programmer-- and <% %>
                              get replaced immediately after its return.


                              > In an OO model, I think we could achieve something like this as in:
                              >
                              > my $pgloop = My::Pgloop->new(
                              > ASP => $asp,
                              > Attrib => { sth => $sth },
                              > Content => \$data_within,
                              > };
                              > my $pgimage = My::PgImage->new(
                              > ASP => $asp,
                              > Attrib => { pg=>"__PG__" sku=>"__SKU__" },
                              > Parent => $pgloop
                              > };
                              > $pgimage->execute(\'');
                              > $pgloop->execute(\$final_data_output_within);


                              > This pre/post processing model would allow pgimage to
                              > work with $self->{Parent}{sth}, or pgloop could populate
                              > its own data in this way. Output from pgimage could be
                              > trapped and inlined, passed into the execute() function
                              > for pgloop.

                              Hmm- sounds a little complicated. Not to mention you are exposing a lot of the
                              $asp guts to the programmer/user that way and the goal should be the exact
                              opposite-- to abstract that away from the programmer and toward the
                              web-monkey/end-user...?


                              > > Another useful thing might be a <def> field (define) field that could
                              > > construct artificial tokens based on expression-manipulation of existing
                              > > data available in the dataset at time of rendering. That way you could
                              > > have a cost field and apply a markup value to it and come up with an
                              > > artificial, but usable price token.
                              > >
                              > > <my:sub>
                              > > <define>PRICE:COST*1.2</define>
                              > > The cost of this item is __COST__ and it is currently selling for
                              > > __PRICE__. </my:sub>

                              > If we have a preprocessing stage like above,

                              That is really a weak example actually. And after thinking about it awhile, I
                              think I agree with you that having <define> blocks is a bad idea. While it
                              might be useful to have that sort of flexibility, in reality it would be a
                              bad idea to depend on a number hard-coded into the html body to define the
                              markup value of the price (to use the example)-- and might encourage
                              programmers (who oughta know better) to do silly things.



                              In my own project that I'm currently working on-- I have two major issues (at
                              least as bounded by the context of this discussion and in trying to resolve
                              it using tools developed herein)-- and they are:

                              1) Choosing between a Regular-Price and a Sale-Price (which are both retrieved
                              during the record fetch) based upon truth of the 'on-sale' flag.

                              2a) Wanting to have a slightly different rendering-- conditional if the item
                              is on-sale vs. not on-sale.

                              2b) Conditional blocks of code-- eg. if the item has a full-description, I
                              want to show it (and the header that says "Full Description" or whatever) or
                              nothing at all if not.


                              In thinking through some stuff-- token rendering is less important and so are
                              format strings than I was making them out to be before-- though the simple
                              format strings are still quite useful, imo, and eliminate more complicated
                              coding because.. you can always define my:subs to handle token-rendering,
                              formatting, and (I think) eliminating the need for explicit token definitions
                              (defines). So in the earlier example where it went to define a __PRICE__
                              token based on a __COST__ token times a multiplier, you could instead do
                              something like:

                              <my:markup cost="__COST__" mult="1.2"/>

                              or

                              <my:markup cost="__COST__" mult="<%=$mult%>"/>

                              if post-processing were available-- actually this particular example works
                              either way, doesn't it...

                              I think you should keep the <fmt>PRICE:%.2f</fmt> stuff available. That is
                              definately a handy short-cut for oft-used and simple field formatting, and
                              happens in an easy-to-understand way. And it doesn't get in the way of, or
                              preclude the more powerful xmlsub method I just illustrated.

                              So the earlier example could be processed like this instead:

                              <my:sub>
                              <fmt>COST:%.2f</fmt>
                              The cost of this item is __COST__ and it is currently selling for <my:markup
                              cost="__COST__" mult="1.2"/>.
                              </my:sub>

                              or using post-processing:

                              <my:sub>
                              <fmt>COST:%.2f</fmt>
                              The cost of this item is __COST__ and it is currently selling for <my:markup
                              cost="__COST__" mult="<%=$mult%>"/>.
                              </my:sub>


                              This seems like a much easier way to handle it and it fits into the current
                              framework much easier and with almost no modification to the current setup.
                              In fact, if you didn't change a thing you could still do 99% of this with the
                              render function-- you just couldn't deal with the post-processing bit (which
                              I already pointed out isn't really an issue in this particular example
                              anyway).



                              So the only real problem left comes down to handling the
                              "(blech>blah)?foo:bar" type logic and full-fledged conditional blocks.


                              > In a pre-process model, the if/else children could be evaluated by the
                              > parent at parent->new() time, or could look at the parent data at their
                              > if->new() time. If ASP <% if() { } %> will still be supported, within,
                              > then that could be evaluated at parent->new() time by simply doing:
                              >
                              > $output = $Response->TrapInclude(\$content);

                              Actually I was thinking something very similar but for another reason-- if you
                              use delayed processing, like I describe above, conditionals actually get
                              pretty easy I think. You just build them into the my:sub "$body" text and let
                              the post-processing pick them up.

                              I think you could handle the ()?: construct with a my:sub too actually-- do
                              something like:

                              <my:price reg="__REG_PRICE__" sale="__SALE_PRICE__" onsale="__ONSALE__"/>

                              Though it might be prettier if there were a special construct for it:

                              __(__ONSALE__?__SALE_PRICE__:__REG_PRICE__)__

                              I think would do it-- and actually, that could simply be handled by the
                              renderer func, and would internally get translated into:

                              <%=($$hash{onsale})?$$hash{sale_price}:$$hash{reg_price}%>

                              Which would work just fine when post-processed. Or, seeing as how you already
                              have the __( )__ nomenclature to distinguish it, you could even shorten the
                              construct to:

                              __(ONSALE?SALE_PRICE:REG_PRICE)__

                              since its going to be handled special anyway-- and that gets intuitive again.


                              > where that will execute the content without needing a post processing model
                              > at all. Hmmm, I kind of like where this is going. :) Of course its
                              > totally different that what we have today.

                              Heh- not anymore ;)

                              All you need to do is make the one adjustment to handle <% %> subs post
                              instead of pre and I think the render function can handle the inbetween
                              stuff. The __TOKEN__ format is very comfortable and intuitive to me in this
                              instance. It seems very obvious that they are serving as placeholders for
                              yet-to-be-in-scope data. And by delaying the <% %> processing, you allow
                              substitution to occur _before_ conditional blocks take place.


                              What is your take on all this?

                              I think we've just descibed a very functional, useable processing paradigm
                              that fits with the current "feel" of the asp system, and with the single
                              exception of moving <% %> substitution to post-processing, you don't have to
                              make any other radical changes to the Apache::ASP framework or api (at least
                              I don't think you do).

                              Your thoughts?


                              John


                              --------------------------------------------------------------------------------
                              Check out http://www.Wizard.Org for great deals on Electronic Parts
                              *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                              --------------------------------------------------------------------------------
                              ** Affordable Online Store w/Merchant Card Processing & Paypal **
                              Write to us: sales@... -- Get your Store Online Today!
                              --------------------------------------------------------------------------------



                              ---------------------------------------------------------------------
                              To unsubscribe, e-mail: asp-unsubscribe@...
                              For additional commands, e-mail: asp-help@...
                            • Brat Wizard
                              A follow-up to my last post... adding this line to the render func: $tmpl =~ s/__ ((.*?) )__/ /gm; # fixup embedded tests Allows this construct to be
                              Message 14 of 16 , Sep 21, 2002
                              View Source
                              • 0 Attachment
                                A follow-up to my last post... adding this line to the render func:

                                $tmpl =~ s/__\((.*?)\)__/<%=($1)%>/gm; # fixup embedded tests

                                Allows this construct to be used:

                                __(__F_ONSALE__?'YES':'NO')__

                                These constructs also work as expected:

                                Item on sale? Yes or No:
                                __(__F_ONSALE__?'YES':'NO')__

                                Item NOT on sale? Yes or No:
                                __(!__F_ONSALE__?'YES':'NO')__

                                Price > 5? Yes or No
                                __(__AMT_PRICE__>5?'YES':'NO')__

                                Item on Sale? Sale Price or Reg Price:
                                __(__F_ONSALE__?__AMT_SALE__:__AMT_PRICE__)__

                                Here is the complete render func to date:

                                sub render { ## process a body-template string and render appropriately
                                my ($tmpl, $hash, $fmt) = @_;
                                $tmpl =~ s/__\[(.*?)\]__/<$1>/gm; # fixup delayed-embedded xmlsubs
                                $tmpl =~ s/__\((.*?)\)__/<%=($1)%>/gm; # fixup embedded tests
                                while ($tmpl =~ /__(.*?)__/) {
                                my $TOKEN = $1; my $token = lc($TOKEN);
                                if ((my $fmt = $$fmt{$TOKEN}) ne undef) {
                                # to-uppercase
                                if ($fmt =~ /^%uc/i) { $fmt =~ s/[^0-9]//gm;
                                $$hash{$tok
                                en} = uc(substr($$hash{$token}, 0, $fmt || length($$hash{$token}))); }
                                # to-lowercase
                                elsif ($fmt =~ /^%lc/i) { $fmt =~ s/[^0-9]//gm;
                                $$hash{$
                                token} = lc(substr($$hash{$token}, 0, $fmt || length($$hash{$token}))); }
                                # picture
                                else { $$hash{$token} = sprintf($fmt, $$hash{$token});
                                }
                                }
                                $tmpl =~ s/__${TOKEN}__/$$hash{$token}/gme;
                                }
                                $Response->Include(\$tmpl);
                                }

                                __END__


                                This is getting cool :)

                                John





                                --

                                --------------------------------------------------------------------------------
                                Check out http://www.Wizard.Org for great deals on Electronic Parts
                                *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                                --------------------------------------------------------------------------------
                                ** Affordable Online Store w/Merchant Card Processing & Paypal **
                                Write to us: sales@... -- Get your Store Online Today!
                                --------------------------------------------------------------------------------





                                ---------------------------------------------------------------------
                                To unsubscribe, e-mail: asp-unsubscribe@...
                                For additional commands, e-mail: asp-help@...
                              • Josh Chamas
                                ... Right. I would never take away the current style/method of XMLSubs, just add to it like you suggest. ... So then the parent XMLSubs output would be then
                                Message 15 of 16 , Sep 21, 2002
                                View Source
                                • 0 Attachment
                                  Brat Wizard wrote:
                                  >
                                  > Josh- why not make it a simple directive, like a pragma-- then it could be
                                  > specified inline by the end-user whenever (and if-ever) they need it one way
                                  > or the other.
                                  >
                                  > Perhaps something like:
                                  >
                                  > $Apache::ASP::XMLSubsPostProc = 1
                                  >

                                  Right. I would never take away the current style/method of XMLSubs,
                                  just add to it like you suggest.

                                  > <my:sub>
                                  > <my:nestedsub><%=$blech%> __TOKEN1__</my:nestedsub>
                                  > <%=$foobar%> __TOKEN2__
                                  > </my:sub>
                                  >
                                  > You could wait until after the first my:sub had been called to interpret the
                                  > rest-- just process everything post. In my thinking __TOKEN1__ and __TOKEN2__
                                  > would get resolved by the renderer function on the first pass and
                                  > <my:nestedsub>, $blech, and $foobar, would get processed immediately
                                  > afterwards-- after the tokens had been substituted.
                                  >
                                  > How would that work out do you think?
                                  >

                                  So then the parent XMLSubs output would be then evaluated
                                  at runtime as ASP script automatically by the system. That
                                  is an interesting way of looking at doing the pre-processing.

                                  The only problem with this model is that runtime parsing/eval
                                  of the code would be expensive. The other preprocessing model
                                  that I was considering would not do ANY inner code substitution
                                  on its own, leaving this to the XMLSubs definition to do if
                                  it wanted to.

                                  I am not sure which one I would lean to more, but they are both
                                  interesting models.

                                  >>my $pgimage = My::PgImage->new(
                                  >> ASP => $asp,
                                  >> Attrib => { pg=>"__PG__" sku=>"__SKU__" },
                                  >> Parent => $pgloop
                                  >>};
                                  >>$pgimage->execute(\'');
                                  >>$pgloop->execute(\$final_data_output_within);
                                  >
                                  >
                                  >
                                  >>This pre/post processing model would allow pgimage to
                                  >>work with $self->{Parent}{sth}, or pgloop could populate
                                  >>its own data in this way. Output from pgimage could be
                                  >>trapped and inlined, passed into the execute() function
                                  >>for pgloop.
                                  >
                                  >
                                  > Hmm- sounds a little complicated. Not to mention you are exposing a lot of the
                                  > $asp guts to the programmer/user that way and the goal should be the exact
                                  > opposite-- to abstract that away from the programmer and toward the
                                  > web-monkey/end-user...?
                                  >
                                  >

                                  This was just an example of how the preprocessing model would
                                  get executed. This would be more for the XMLSubs definer to
                                  worry about. I ideally to the end user, things would just work.
                                  I believe that XMLSubs will have to grow in complexity to be
                                  able to do really doo things that other platform taglib functionality
                                  offers. I will be looking hard as JSP & AxKit before I do any
                                  next generation XMLSubs for sure.

                                  >
                                  > Actually I was thinking something very similar but for another reason-- if you
                                  > use delayed processing, like I describe above, conditionals actually get
                                  > pretty easy I think. You just build them into the my:sub "$body" text and let
                                  > the post-processing pick them up.
                                  >

                                  I see the power of the preprocessing + execute output during post
                                  processing model. The speed issue is the only one I have to get
                                  over here. I'll look at some taglib libraries that I would like
                                  to implement in Apache::ASP & see what kind of power we need here.
                                  It may be that some things are only possible with the kind of
                                  power that you suggest, and its a very interesting idea giving
                                  the XMLSubs programmer the ability to rewrite the code on the fly.

                                  > All you need to do is make the one adjustment to handle <% %> subs post
                                  > instead of pre and I think the render function can handle the inbetween
                                  > stuff. The __TOKEN__ format is very comfortable and intuitive to me in this
                                  > instance. It seems very obvious that they are serving as placeholders for
                                  > yet-to-be-in-scope data. And by delaying the <% %> processing, you allow
                                  > substitution to occur _before_ conditional blocks take place.
                                  >
                                  >
                                  > What is your take on all this?
                                  >
                                  > I think we've just descibed a very functional, useable processing paradigm
                                  > that fits with the current "feel" of the asp system, and with the single
                                  > exception of moving <% %> substitution to post-processing, you don't have to
                                  > make any other radical changes to the Apache::ASP framework or api (at least
                                  > I don't think you do).
                                  >
                                  > Your thoughts?
                                  >

                                  Pretty good stuff. I'll definately be following up on this later
                                  when I go to implement, so stay tuned.

                                  Regards,

                                  Josh
                                  ________________________________________________________________
                                  Josh Chamas, Founder phone:925-552-0128
                                  Chamas Enterprises Inc. http://www.chamas.com
                                  NodeWorks Link Checking http://www.nodeworks.com


                                  ---------------------------------------------------------------------
                                  To unsubscribe, e-mail: asp-unsubscribe@...
                                  For additional commands, e-mail: asp-help@...
                                • Brat Wizard
                                  Of course, you could also put just the info to be included into a separate file and allow it to be included at a judicious moment... (nah, that would be too
                                  Message 16 of 16 , Sep 22, 2002
                                  View Source
                                  • 0 Attachment
                                    Of course, you could also put just the info to be included into a separate
                                    file and allow it to be included at a judicious moment... (nah, that would be
                                    too easy ;)

                                    But the one thing that _doesn't_ allow for, and the reason why I myself have
                                    been working on the problem-- is putting together something you can let the
                                    end-user (the buyer of the account) create/customize/or otherwise abuse w/o
                                    worrying about compromising the sanctity of the system in the process. They
                                    can only supply tokens to be substituted and simple formatting directives,
                                    and not actualy code (although the ()?: structure I presented does allow
                                    actual code to be executed, something I would have to deal with somehow).



                                    > I see the power of the preprocessing + execute output during post
                                    > processing model. The speed issue is the only one I have to get
                                    > over here.

                                    --

                                    --------------------------------------------------------------------------------
                                    Check out http://www.Wizard.Org for great deals on Electronic Parts
                                    *NEW* Computer Parts & Accessories - Drives - LCD - Systems - Linux
                                    --------------------------------------------------------------------------------
                                    ** Affordable Online Store w/Merchant Card Processing & Paypal **
                                    Write to us: sales@... -- Get your Store Online Today!
                                    --------------------------------------------------------------------------------



                                    ---------------------------------------------------------------------
                                    To unsubscribe, e-mail: asp-unsubscribe@...
                                    For additional commands, e-mail: asp-help@...
                                  Your message has been successfully submitted and would be delivered to recipients shortly.