ebdb652000-01-14Martin Nilsson // This is a roxen module. Copyright © 1996 - 2000, Idonex AB.
4817401999-08-13Martin Nilsson // #define _stat id->misc->defines[" _stat"] #define _error id->misc->defines[" _error"] #define _extra_heads id->misc->defines[" _extra_heads"] #define _rettext id->misc->defines[" _rettext"] #define _ok id->misc->defines[" _ok"]
1036372000-01-24Martin Nilsson constant cvs_version="$Id: rxmltags.pike,v 1.47 2000/01/24 19:21:31 nilsson Exp $";
4817401999-08-13Martin Nilsson constant thread_safe=1;
bfd5fb1999-10-08Martin Nilsson constant language = roxen->language;
4817401999-08-13Martin Nilsson  #include <module.h> inherit "module"; inherit "roxenlib"; // ---------------- Module registration stuff ----------------
0be6412000-01-18Martin Nilsson constant module_type = MODULE_PARSER | MODULE_PROVIDER; constant module_name = "RXML 1.4 tags"; constant module_doc = "This module adds a lot of RXML tags.";
16509b1999-12-14Martin Nilsson void create()
4817401999-08-13Martin Nilsson { defvar("insert_href",1,"Allow &lt;insert href&gt;.", TYPE_FLAG|VAR_MORE, "Should the usage of &lt;insert href&gt; be allowed?"); }
16509b1999-12-14Martin Nilsson void start()
659d4b1999-10-18Martin Nilsson {
ecab8b2000-01-23Martin Nilsson  add_api_function("query_modified", api_query_modified, ({ "string" }));
0be6412000-01-18Martin Nilsson  query_tag_set()->prepare_context=set_entities;
4817401999-08-13Martin Nilsson }
b7e95b1999-12-14Martin Nilsson string query_provides() { return "modified"; } TAGDOCUMENTATION;
cfe42b1999-12-07Martin Nilsson #ifdef manual constant tagdoc=(["roxen-automatic-charset-variable":"<desc tag></desc>",
e272382000-01-23Kenneth Johansson "aconf":#"<desc cont> Creates a link that can modify the persistent states in the cookie RoxenConfig. </desc> <attr name=href value=uri> Indicates which page should be linked to, if any other than the present one. </attr> <attr name=add value=string> The 'cookie' or 'cookies' that should be added, in a comma seperated list. </attr> <attr name=drop value=string> The 'cookie' or 'cookies' that should be droped, in a comma seperated list. </attr> <attr name=class value=string> This CSS class definition will apply to the a-element. </attr> <p>All other attributes will be inherited by the generated a tag.</p>", "append":#"<desc tag> Appends a value to a variable. The variable attribute and one more is required. </desc> <attr name=variable value=string> The name of the variable. </attr> <attr name=value value=string> The value the variable should have appended. </attr> </attr name=from value=string> The name of another variable that the value should be copied from. </attr> <attr name=other value=string> The name of a id->misc->variables that the value should be copied from. </attr>", "apre":#"<desc cont> Creates a link that can modify prestates. </desc> <attr name=href value=uri> Indicates which page should be linked to, if any other than the present one. </attr> <attr name=add value=string> The prestate or prestates that should be added, in a comma seperated list. </attr> <attr name=drop value=string> The prestate or prestates that should be droped, in a comma seperated list. </attr> <attr name=class value=string> This CSS class definition will apply to the a-element. </attr> All other attributes will be inherited by the generated a tag", "auth-required":#"<desc tag> Adds an HTTP auth required header and return code, that will force the user to supply a login name and password. This tag is needed when using access control in RXML in order for the user to be prompted to login. </desc> <attr name=realm value=string> Hmm?? </attr> <attr name=message value=string> Returns a message if a login failed. ******Korrekt???******** </attr>", "autoformat":#"<desc cont> Replaces newlines with <tag>br</tag>:s. </desc> <attr name=nobr> Do not replace newlines with <tag>br</tag>:s. </attr> <attr name=p> Replace double newlines with <tag>p</tag>:s. </attr> <attr name=class value=string> This CSS definition will be applied on the p elements. </attr>", "cache":#"<desc cont> </desc>
1036372000-01-24Martin Nilsson <attr name=key value=string>
e272382000-01-23Kenneth Johansson  </attr>", "catch":#"<desc cont></desc>", "configimage":#"<desc tag> Returns one of the configuration images. The src attribute is required. </desc> <attr name=src value=string> The name of the picture to show. </attr> <attr name=border value=number> The image border when used as a link. Default is 0. </attr> <attr name=alt value=string> The picture description. Default is the src string. </attr> <attr name=class value=string> This CSS class definition will be applied to the image. </attr> All other attributes will be inherited by the generated img tag.", "configurl":#"<desc tag> Returns a URL to the configuration interface. </desc>", "cset":#"<desc cont></desc>", "crypt":#"<desc cont></desc>", "date":#"<desc tag> Inserts the time and date. Does not require attributes. </desc> <attr name=unix-time value=number> Display this time instead of the current. </attr> <attr name=years value=number> Add this number of years to the result. </attr> <attr name=months value=number> Add this number of months to the result. </attr> <attr name=weeks value=number> Add this number of weeks to the result. </attr> <attr name=days value=number> Add this number of days to the result. </attr> <attr name=hours value=number> Add this number of hours to the result. </attr> <attr name=beats value=number> Add this number of beats to the result. </attr> <attr name=minutes value=number> Add this number of minutes to the result. </attr> <attr name=seconds value=number> Add this number of seconds to the result. </attr> <attr name=adjust value=number> Add this number of seconds to the result. </attr> <attr name=brief> Show in brief format. </attr> <attr name=time> Show only time. </attr> <attr name=date> Show only date. </attr> <attr name=type value=string,ordered,iso,discordian,stardate,number> Defines in which format the date should be displayed in. </attr> <attr name=part value=year,month,day,wday,date,mday,hour,minute,second,yday,beat,week,seconds> Defines which part of the date should be displayed. Day and wday is the same. Date and mday is the same. Yday is the day number of the year. Seconds is unix time type. Only the types string, number and ordered applies when the part attribute is used. </attr> <attr name=lang value=language_code> Defines in what language the a string will be presented in. </attr> <attr name=case value=upper,lower,capitalized> Changes the case of the output to upper, lower or capitalized. </attr> <attr name=prec value=number> The number of decimals in the stardate. </attr>", "debug":#"<desc tag> Helps debugging RXML-pages as well as modules. When debugging mode is turned on, all error messages will be displayed in the HTML code. </desc> <attr name=on> Turns debug mode on. </attr> <attr name=off> Turns debug mode off. </attr> <attr name=toggle> Toggles debug mode. </attr> <attr name=showid value=string> Shows a part of the id object. E.g. showid='id->request_headers'. </attr>", "dec":#"<desc tag> Subtracts 1 from a variable. Attribute variable is required. </desc> <attr name=variable value=string> The variable to be decremented. </attr>", "default":#"<desc cont> Makes it easier to give default values to '<tag>select</tag>' or '<tag>checkbox</tag>' form elements. <p>The <tag>default</tag> container tag is placed around the form element it should give a default value.</p> <p>This tag is particularly useful in combination with database tags.</p> </desc> <attr name=value value=string> The value to set. </attr> <attr name=separator value=string> </attr> <attr name=name value=string> Only affect form element with this name. </attr> <attr name=variable value=string> </attr>", "doc":#"<desc cont> Eases documentation by replacing '{', '}' and '&' with '<', '>' and '&'. No attributes required. </desc> <attr name=quote> Instead of replacing '{' and '}', '<' and '>' is replaced with '&amp;lt;' and '&amp;gt;'. </attr> <attr name=pre> The result is encapsulated within a <tag>pre</tag> container. </attr> <attr name=class value=string> This CSS definition will be applied on the pre element. </attr>", "expire-time":#"<desc tag> Finns ingen tidigare doc. </desc> <attr name=now> </attr> <attr name=hours value=number> </attr> <attr name=beats value=number> </attr> <attr name=minutes value=number> </attr> <attr name=seconds value=number> </attr> <attr name=days value=number> </attr> <attr name=weeks value=number> </attr> <attr name=months value=number> </attr> <attr <name=years value=number> </attr>", "for":#"<desc cont> Makes it possible to create loops in RXML. </desc> <attr name=from value=number> Initial value of the loop variable. </attr> <attr name=step value=number> How much to increment the variable per loop iteration. By default one. </attr> <attr name=to value=number> How much the loop variable should be incremented to. </attr> <attr name=variable value=name> Name of the loop variable. </attr>", "foreach":#"<desc cont> </desc> <attr name=variable> </attr> <attr name=variables> </attr> <attr name=in> </attr>", "formoutput":#"<desc cont></desc>", "fsize":#"<desc tag> </desc> <attr name=file value=string> </attr>", "gauge":#"<desc cont> Measures how much CPU time it takes to run its contents through the RXML parser. </desc> <attr name=define value=string> </attr> <attr name=silent> </attr> <attr name=timeonly> </attr> <attr name=resultonly> </attr>", "header":#"<desc tag>sfdjhbskdg</desc>", "imgs":#"<desc tag> Generates a image tag with proper dimensions. Attribute src is required. </desc> <attr name=src value=string> The name of the file that should be shown. </attr> <attr name=alt value=string> Description of the image. Default is the image file name. </attr> All other attributes will be inherited by the generated img tag.", "inc":#"<desc tag> Adds 1 to a variable. Attribute variable is required. </desc> <attr name=variable value=string> The variable to be incremented. </attr>", "insert":#"<desc tag> Inserts a file, variable or other object into a webpage. One attribute is required. </desc> <attr name=variable value=string> Inserts the value of that variable. </attr> <attr name=variables> Inserts a variable listing. </attr> <attr name=cookies> Inserts a cookie listing. </attr> <attr name=cookie value=string> Inserts the value of that cookie. </attr> <attr name=file value=string> Inserts the contents of that file. </attr> <attr name=href value=string> Inserts the contents at that URL. </attr> <attr name=other value=string> Inserts a misc variable (id->misc->variables). </attr> <attr name=quote value=html,none> How the inserted data should be quoted. Default is 'html', except for href and file where it's 'none'. </attr>", "maketag":#"<desc cont> This tag creates tags. The contents of the container will be put into the contents of the produced container. Requires the name attribute. </desc> <attr name=name value=string> The name of the tag. </attr> <attr name=noxml> Tags should not be terminated with a trailing slash. </attr> <attr name=type value=tag,container> What kind of tag should be produced. Default is tag. </attr> Inside the maketag container the container attrib is defined. It is used to add attributes to the produced tag. It has the required attribute attrib, which is the name of the attribute. The contents of the attribute container will be the attribute value. E.g. <p>&lt;maketag name=replace type=container&gt; &lt;attrib name=from&gt;A&lt;/attrib&gt; &lt;attrib name=to&gt;U&lt;/attrib&gt; MAD &lt;/maketag&gt; will result in &lt;replace from=A to=U&gt;MAD&lt;/replace&gt; &lt;/pre&gt;</p>", "modified":#"<desc tag> Prints when or by whom a page was last modified, by default the current page. </desc> <attr name=by> Print by whom the page was modified. Takes the same attributes as the <tag><ref type=tag>user</ref></tag> tag. This attribute requires a userdatabase. </attr> <attr name=date> Print the modification date. Takes all the date attributes in the <tag><ref type=tag>date</ref></tag> tag. </attr> <attr name=file value=path> Get information from this file rather than the current page. </attr> <attr name=realfile value=path> Get information from this file in the computers filesystem rather than Roxen Webserver's virtual filesystem. </attr>",
8859351999-11-25Martin Nilsson "quote":"<desc tag></desc>",
e272382000-01-23Kenneth Johansson  "random":#"<desc cont> Randomly chooses a message from its contents. </desc> <attr name=separator value=string> The separator used to separate the messages, by default newline. </attr>", "recursive-output":#"<desc cont> </desc> <attr name=limit value=number> </attr> <attr name=inside value=string> </attr> <attr name=outside value=string> </attr> <attr name=separator value=string> </attr>", "redirect":#"<desc tag> Redirects the user to another page. Requires the to attribute. </desc> <attr name=to value=string> Where the user should be sent to. </attr> <attr name=add value=string> The prestate or prestates that should be added, in a comma seperated list. </attr> <attr name=drop value=string> The prestate or prestates that should be dropped, in a comma seperated list. </attr> <attr name=text value=string> Tja, steker greker kanske? </attr>", "remove-cookie":#"<desc tag> Removes a cookie. </desc> <attr name=name> Name of the cookie to remove. </attr>
1036372000-01-24Martin Nilsson <attr name=value value=text> Even though the cookie has been marked as expired some browsers will not remove the cookie until it is shut down. The text provided with this attribute will be the cookies intemediate value.
e272382000-01-23Kenneth Johansson </attr> Note that removing a cookie won't take effect until the next page load.", "repeat":#"<desc cont> Repeats the contents until a <tag>leave</tag> tag has been found. Requires no attributes. </desc> <attr name=maxloops> The maximum number of loops. Default is 10000. </attr>", "replace":#"<desc cont> Replaces strings in the contents with other strings. Requires the from attribute. </desc> <attr name=from value=string> String or list of strings that should be replaced. </attr> <attr name=to value=string> String or list of strings with the replacement strings. Default is the empty string. </attr> <attr name=separator value=string> Defines what string should seperate the strings in the from and to attributes. Default is ','. </attr> <attr name=type value=word,words> Word means that a single string should be replaced. Words that from and to are lists. Default is word. </attr>", "return":#"<desc tag> Changes the HTTP return code for this page. See the Appendix for a list of HTTP return codes. </desc> <attr name=code> The return code to set. </attr>", "roxen":#"<desc tag> Returns a nice Roxen logo. </desc> <attr name=size value=small,medium,large> Defines the size of the image. Default is small. </attr> <attr name=color value=blue,green,purple,brown> Defines the color of the image. Default is blue. </attr> <attr name=alt value=string> The image description. Default is 'Powered by Roxen'. </attr> <attr name=border value=number> The image border. Default is 0. </attr> <attr name=class value=string> This CSS definition will be applied on the img element. </attr> All other attributes will be inherited by the generated img tag.", "scope":#"<desc cont> Creates a different variable scope. Variable changes inside the scope container will not affect variables in the rest of the page. Variables set outside the scope is not available inside the scope unless the extend attribute is used. No attributes are required. </desc> <attr name=extend> If set, all variables will be copied into the scope. </attr> <attr name=truth> Make a scope for truth as well. The previous true/false state will be inherited into the scope, but changes in the state will not affect anything outside the scope. </attr>", "set":#"<desc tag> Sets a variable. The variable attribute is required. </desc> <attr name=variable value=string> The name of the variable. </attr> <attr name=value value=string> The value the variable should have. </attr> <attr name=expr value=string> An expression whose evaluated value the variable should have. </attr> <attr name=from value=string> The name of another variable that the value should be copied from. </attr> <attr name=other value=string> The name of a id->misc->variables that the value should be copied from. </attr> <attr name=eval value=string> An RXML expression whose evaluated value the variable should have. </attr>", "set-cookie":#"<desc tag> Sets a cookie that will be stored by the user's browser. This is a simple and effective way of storing data that is local to the user. The cookie will be persistent, the next time the user visits the site, she will bring the cookie with her. </desc> <attr name=name value=string> The name of the cookie. </attr> <attr name=seconds> Add this number of seconds to the time the cookie is kept. </attr> <attr name=minutes> Add this number of minutes to the time the cookie is kept. </attr> <attr name=hours> Add this number of hours to the time the cookie is kept. </attr> <attr name=days> Add this number of days to the time the cookie is kept. </attr> <attr name=weeks> Add this number of weeks to the time the cookie is kept. </attr> <attr name=months> Add this number of months to the time the cookie is kept. </attr> <attr name=years> Add this number of years to the time the cookie is kept. </attr> <attr name=persistent> Keep the cookie for two years. </attr> <attr name=value value=string> The value the cookie will be set to. </attr> <attr name=path value=string> ????????????? </attr> It is not possible to set the date beyond year 2038. By default the cookie will be kept until the year 2038. Note that the change of a cookie will not take effect until the next page load.", "set-max-cache":#"<desc tag> </desc> <attr name=time value=number> </attr>", "smallcaps":#"<desc cont> This tag prints the contents in smallcaps. If the size attribute is given, font tags will be used, otherwise big and small tags will be used. </desc> <attr name=space> Put a space between every character. </attr> <attr name=class value=string> Apply this CSS style on all elements. </attr> <attr name=smallclass value=string> Apply this CSS style on all small elements. </attr> <attr name=bigclass value=string> Apply this CSS style on all big elements. </attr> <attr name=size value=number> Use font tags, and this number as big size. </attr> <attr name=small value=number> Size of the small tags. Only applies when size is specified. Default is size-1. </attr>", "sort":#"<desc cont> Sorts the contents. No attributes required. </desc> <attr name=separator value=string> Defines what the strings to be sorted are separated with. </attr> <attr name=reverse> Reversed order sort. </attr>", "throw":#"<desc cont></desc>", "trimlines":#"<desc cont> This tag removes all empty lines from the contents. </desc>", "unset":#" <desc tag> Unsets a variable, i.e. removes it. The variable attribute is required. </desc> <attr name=variable value=string> The name of the variable. </attr>", "user":#"<desc tag> Prints information about the specified user. By default, the full name of the user and her e-mail address will be printed, with a mailto link and link to the home page of that user. The <tag>user</tag> tag requires an authentication module to work. </desc> <attr name=email> Only print the e-mail address of the user, with no link. </attr> <attr name=link> Include links. Only meaningful together with the realname or email attribute. </attr> <attr name=name> The login name of the user. </attr> <attr name=nolink> Don't include the links. </attr> <attr name=realname> Only print the full name of the user, with no link. </attr>",
cfe42b1999-12-07Martin Nilsson  ]); #endif
8859351999-11-25Martin Nilsson  constant permitted = "123456789xabcdefnt\"XABCDEFlo<>=0-*+/%%|()"/"";
4817401999-08-13Martin Nilsson  string sexpr_eval(string what) { array q = what/""; what = "mixed foo(){ return "+(q-(q-permitted))*""+";}"; return (string)compile_string( what )()->foo(); }
b53b751999-10-09Martin Nilsson 
0be6412000-01-18Martin Nilsson // ----------------- Entities ---------------------- class Entity_page_realfile { string rxml_var_eval(RXML.Context c) { return c->id->realfile||""; } }
ecab8b2000-01-23Martin Nilsson class Entity_page_virtroot {
0be6412000-01-18Martin Nilsson  string rxml_var_eval(RXML.Context c) { return c->id->virtfile||""; } }
ecab8b2000-01-23Martin Nilsson class Entity_page_virtfile { string rxml_var_eval(RXML.Context c) { return c->id->not_query; } }
c6b6c92000-01-21Martin Nilsson class Entity_page_url {
0be6412000-01-18Martin Nilsson  string rxml_var_eval(RXML.Context c) { return c->id->raw_url; } }
c6b6c92000-01-21Martin Nilsson class Entity_page_last_true {
0be6412000-01-18Martin Nilsson  int rxml_var_eval(RXML.Context c) { return c->id->misc->defines[" _ok"]; } } class Entity_page_language {
c6b6c92000-01-21Martin Nilsson  string rxml_var_eval(RXML.Context c) { return c->id->misc->defines->language || ""; }
0be6412000-01-18Martin Nilsson }
ecab8b2000-01-23Martin Nilsson class Entity_page_scope { string rxml_var_eval(RXML.Context c) { return c->current_scope()||""; } }
0be6412000-01-18Martin Nilsson mapping page_scope=(["realfile":Entity_page_realfile(),
ecab8b2000-01-23Martin Nilsson  "virtroot":Entity_page_virtroot(), "virtfile":Entity_page_virtfile(),
c6b6c92000-01-21Martin Nilsson  "url":Entity_page_url(), "last_true":Entity_page_last_true(),
ecab8b2000-01-23Martin Nilsson  "language":Entity_page_language(), "scope":Entity_page_scope() ]);
0be6412000-01-18Martin Nilsson 
ecab8b2000-01-23Martin Nilsson class Entity_client_referrer { string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0;
093fd32000-01-23Martin Nilsson  array referrer=c->id->referrer; return referrer && sizeof(referrer)?referrer[0]:"";
ecab8b2000-01-23Martin Nilsson  }
0be6412000-01-18Martin Nilsson }
c6b6c92000-01-21Martin Nilsson class Entity_client_name {
ecab8b2000-01-23Martin Nilsson  string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0;
093fd32000-01-23Martin Nilsson  array client=c->id->client; return client && sizeof(client)?client[0]:"";
ecab8b2000-01-23Martin Nilsson  }
0be6412000-01-18Martin Nilsson }
c6481f2000-01-21Martin Nilsson class Entity_client_ip {
ecab8b2000-01-23Martin Nilsson  string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0; return c->id->remoteaddr; } } class Entity_client_accept_language { string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0; if(!c->id->misc["accept-language"]) return ""; return c->id->misc["accept-language"][0]; } } class Entity_client_accept_languages { string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0; if(!c->id->misc["accept-language"]) return "";
093fd32000-01-23Martin Nilsson  return c->id->misc["accept-language"]*", "; } } class Entity_client_language { string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0; array languages=c->id->misc->pref_languages; if(!languages || !sizeof(languages)) return ""; return languages[0]; } } class Entity_client_languages { string rxml_var_eval(RXML.Context c) { c->id->misc->cacheable=0; array languages=c->id->misc->pref_languages; if(!languages || !sizeof(languages)) return ""; return languages*", ";
ecab8b2000-01-23Martin Nilsson  }
0be6412000-01-18Martin Nilsson }
c6481f2000-01-21Martin Nilsson mapping client_scope=([ "ip":Entity_client_ip(),
c6b6c92000-01-21Martin Nilsson  "name":Entity_client_name(),
ecab8b2000-01-23Martin Nilsson  "referrer":Entity_client_referrer(), "accept_language":Entity_client_accept_language(),
093fd32000-01-23Martin Nilsson  "accept_languages":Entity_client_accept_languages(), "language":Entity_client_language(), "languages":Entity_client_languages()]);
0be6412000-01-18Martin Nilsson  void set_entities(RXML.Context c) {
c6b6c92000-01-21Martin Nilsson  c->extend_scope("page", page_scope); c->extend_scope("client", client_scope);
0be6412000-01-18Martin Nilsson }
4817401999-08-13Martin Nilsson // ------------------- Tags ------------------------
bcde6c1999-11-19Per Hedbor string tag_roxen_automatic_charset_variable( string t, mapping m, RequestID id ) { return make_tag( "input", ([ "type":"hidden", "name":"magic_roxen_automatic_charset_variable", "value":"åäö", ]) ); }
9897451999-10-10Per Hedbor string tag_append( string tag, mapping m, RequestID id )
4817401999-08-13Martin Nilsson { if (m->variable) {
ecab8b2000-01-23Martin Nilsson  RXML.Context context=RXML.get_context(); mixed value=context->user_get_var(m->variable, m->scope); if (m->value) { // Append a value to an entity variable. if (value) value+=m->value;
4817401999-08-13Martin Nilsson  else
ecab8b2000-01-23Martin Nilsson  value=m->value; context->user_set_var(m->variable, value, m->scope); return ""; } if (m->from) { // Append the value of another entity variable. mixed from=context->user_get_var(m->from, m->scope); if(!from) return rxml_error(tag, "From variable doesn't exist.", id); if (value) value+=from;
4817401999-08-13Martin Nilsson  else
ecab8b2000-01-23Martin Nilsson  value=from; context->user_set_var(m->variable, value, m->scope); return ""; } // FIXME: Kill this? if (m->other) { // Append the value of a misc variable to an enityt variable. if (!id->misc->variables || !id->misc->variables[ m->other ])
d93f831999-09-17Martin Nilsson  return rxml_error(tag, "Other variable doesn't exist.", id);
ecab8b2000-01-23Martin Nilsson  if (value) value+=id->misc->variables[ m->other ]; else value=id->misc->variables[ m->other ]; context->user_set_var(m->variable, value, m->scope); return ""; } return rxml_error(tag, "No value specified.", id);
4817401999-08-13Martin Nilsson  } return rxml_error(tag, "Nothing to append from.", id); }
9897451999-10-10Per Hedbor string tag_auth_required (string tagname, mapping args, RequestID id)
4817401999-08-13Martin Nilsson { mapping hdrs = http_auth_required (args->realm, args->message); if (hdrs->error) _error = hdrs->error;
659d4b1999-10-18Martin Nilsson  if (hdrs->extra_heads) _extra_heads += hdrs->extra_heads; // We do not need this as long as hdrs only contains strings and numbers
ecab8b2000-01-23Martin Nilsson  // foreach(indices(hdrs->extra_heads), string tmp)
659d4b1999-10-18Martin Nilsson  // add_http_header(_extra_heads, tmp, hdrs->extra_heads[tmp]);
4817401999-08-13Martin Nilsson  if (hdrs->text) _rettext = hdrs->text; return ""; }
9897451999-10-10Per Hedbor string tag_expire_time(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson { int t=time(); if(!m->now) {
659d4b1999-10-18Martin Nilsson  t+=time_dequantifier(m);
4817401999-08-13Martin Nilsson  CACHE(max(t-time(),0)); } else { NOCACHE();
bfd5fb1999-10-08Martin Nilsson  add_http_header(_extra_heads, "Pragma", "no-cache"); add_http_header(_extra_heads, "Cache-Control", "no-cache");
4817401999-08-13Martin Nilsson  }
bfd5fb1999-10-08Martin Nilsson  add_http_header(_extra_heads, "Expires", http_date(t));
4817401999-08-13Martin Nilsson  return ""; }
9897451999-10-10Per Hedbor string tag_header(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson { if(m->name == "WWW-Authenticate") { string r; if(m->value) { if(!sscanf(m->value, "Realm=%s", r)) r=m->value;
659d4b1999-10-18Martin Nilsson  } else
4817401999-08-13Martin Nilsson  r="Users"; m->value="basic realm=\""+r+"\""; } else if(m->name=="URI") m->value = "<" + m->value + ">";
659d4b1999-10-18Martin Nilsson 
4817401999-08-13Martin Nilsson  if(!(m->value && m->name)) return rxml_error(tag, "Requires both a name and a value.", id);
bfd5fb1999-10-08Martin Nilsson  add_http_header(_extra_heads, m->name, m->value);
4817401999-08-13Martin Nilsson  return ""; }
9897451999-10-10Per Hedbor string tag_redirect(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
0491481999-09-11Martin Stjernholm  if (!(m->to && sizeof (m->to)))
4817401999-08-13Martin Nilsson  return rxml_error(tag, "Requires attribute \"to\".", id); multiset(string) orig_prestate = id->prestate; multiset(string) prestate = (< @indices(orig_prestate) >); if(m->add) { foreach((m->add-" ")/",", string s) prestate[s]=1; m_delete(m,"add"); } if(m->drop) { foreach((m->drop-" ")/",", string s) prestate[s]=0; m_delete(m,"drop"); } id->prestate = prestate; mapping r = http_redirect(m->to, id); id->prestate = orig_prestate; if (r->error) _error = r->error; if (r->extra_heads)
659d4b1999-10-18Martin Nilsson  _extra_heads += r->extra_heads; // We do not need this as long as r only contains strings and numbers // foreach(indices(r->extra_heads), string tmp) // add_http_header(_extra_heads, tmp, r->extra_heads[tmp]);
4817401999-08-13Martin Nilsson  if (m->text) _rettext = m->text; return ""; }
1c79451999-10-17Martin Nilsson string tag_unset(string tag, mapping m, RequestID id) {
ecab8b2000-01-23Martin Nilsson  if(!m->variable && !m->scope) return rxml_error(tag, "Variable not specified.", id); if(!m->variable && m->scope!="roxen") { RXML.get_context()->add_scope(m->scope, ([]) ); return ""; } RXML.get_context()->user_delete_var(m->variable, m->scope);
1c79451999-10-17Martin Nilsson  return ""; }
9897451999-10-10Per Hedbor string tag_set( string tag, mapping m, RequestID id )
4817401999-08-13Martin Nilsson { if (m->variable) {
ecab8b2000-01-23Martin Nilsson  RXML.Context context=RXML.get_context(); if (m->value) { // Set an entity variable to a value. context->user_set_var(m->variable, m->value, m->scope); return ""; } if (m->expr) { // Set an entity variable to an evaluated expression. context->user_set_var(m->variable, sexpr_eval(m->expr), m->scope); return ""; } if (m->from) { // Copy a value from another entity variable. mixed from=context->user_get_var(m->from, m->scope); if(!from) return rxml_error(tag, "From variable doesn't exist.", id); context->user_set_var(m->variable, from, m->scope); return ""; } // FIXME: Kill these? if (m->other) { if (id->misc->variables && id->misc->variables[ m->other ]) { // Set an entity variable to the value of a misc variable context->user_set_var(m->variable, (string)id->misc->variables[m->other], m->scope); return ""; } return rxml_error(tag, "Other variable doesn't exist.", id); } if (m->eval) { // Set an entity variable to the result of some evaluated RXML context->user_set_var(m->variable, parse_rxml(m->eval, id), m->scope); return ""; }
4817401999-08-13Martin Nilsson 
ecab8b2000-01-23Martin Nilsson  return rxml_error(tag, "No value specified.", id);
4817401999-08-13Martin Nilsson  }
d93f831999-09-17Martin Nilsson  return rxml_error(tag, "Variable not specified.", id);
4817401999-08-13Martin Nilsson } string tag_quote(string tagname, mapping m) { #if efun(set_start_quote) if(m->start && strlen(m->start)) set_start_quote(m->start[0]); if(m->end && strlen(m->end)) set_end_quote(m->end[0]); #endif return ""; }
9897451999-10-10Per Hedbor string tag_inc(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
ecab8b2000-01-23Martin Nilsson  if(!m->variable) return rxml_error(tag, "No variable to increment.", id); RXML.Context context=RXML.get_context(); array entity=context->parse_user_var(m->variable, m->scope); if(!context->exist_scope(entity[0])) return rxml_error(tag, "Scope "+entity[0]+" does not exist.", id); int val=(int)m->value||1; context->user_set_var(m->variable, (int)context->user_get_var(m->variable, m->scope)+val, m->scope); return "";
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string tag_dec(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
ecab8b2000-01-23Martin Nilsson  m->value=-(int)m->value||-1; return tag_inc(tag, m, id);
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string|array(string) tag_imgs(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson { string tmp=""; if(m->src) { string file; if(file=id->conf->real_file(fix_relative(m->src, id), id)) { array(int) xysize; if(xysize=Dims.dims()->get(file)) { m->width=(string)xysize[0]; m->height=(string)xysize[1]; }
659d4b1999-10-18Martin Nilsson  else tmp+=" Dimensions quering failed.";
4817401999-08-13Martin Nilsson  }
659d4b1999-10-18Martin Nilsson  else tmp+=" Virtual path failed";
4817401999-08-13Martin Nilsson  if(!m->alt) { array src=m->src/"/"; string src=src[sizeof(src)-1]; m->alt=String.capitalize(replace(src[..sizeof(src)-search(reverse(src),".")-2],"_"," ")); }
ca6ea21999-10-03Johan Sundström  return ({ make_tag("img", m)+(tmp?rxml_error(tag, tmp, id):"") });
4817401999-08-13Martin Nilsson  } return rxml_error(tag, "No src given.", id); }
9897451999-10-10Per Hedbor array(string) tag_roxen(string tagname, mapping m, RequestID id)
4817401999-08-13Martin Nilsson { string size = m->size || "small"; string color = m->color || "blue"; m_delete(m, "color"); m_delete(m, "size"); m->src = "/internal-roxen-power-"+size+"-"+color; m->width = (["small":"100","medium":"200","large":"300"])[size]; m->height = (["small":"35","medium":"60","large":"90"])[size]; if(!m->alt) m->alt="Powered by Roxen"; if(!m->border) m->border="0";
ca6ea21999-10-03Johan Sundström  return ({ "<a href=\"http://www.roxen.com/\">"+make_tag("img", m)+"</a>" });
4817401999-08-13Martin Nilsson }
c4d2a52000-01-03Martin Nilsson string|array(string) tag_debug( string tag_name, mapping m, RequestID id )
4817401999-08-13Martin Nilsson {
c4d2a52000-01-03Martin Nilsson  if (m->showid)
9897451999-10-10Per Hedbor  {
c4d2a52000-01-03Martin Nilsson  array path=lower_case(m->showid)/"->";
4817401999-08-13Martin Nilsson  if(path[0]!="id" || sizeof(path)==1) return "Can only show parts of the id object."; mixed obj=id; foreach(path[1..], string tmp) { if(search(indices(obj),tmp)==-1) return "Could only reach "+tmp+"."; obj=obj[tmp]; }
9897451999-10-10Per Hedbor  return ({ "<pre>"+html_encode_string(sprintf("%O",obj))+"</pre>" });
4817401999-08-13Martin Nilsson  }
c4d2a52000-01-03Martin Nilsson  if (m->off)
4817401999-08-13Martin Nilsson  id->misc->debug = 0;
c4d2a52000-01-03Martin Nilsson  else if (m->toggle)
4817401999-08-13Martin Nilsson  id->misc->debug = !id->misc->debug; else id->misc->debug = 1; return "<!-- Debug is "+(id->misc->debug?"enabled":"disabled")+" -->"; }
9897451999-10-10Per Hedbor string tag_fsize(string tag, mapping args, RequestID id)
4817401999-08-13Martin Nilsson {
ebdb652000-01-14Martin Nilsson  if(args->file) { catch { array s = id->conf->stat_file( fix_relative( args->file, id ), id ); if (s && (s[1]>= 0)) return (string)s[1]; }; if(string s=id->conf->try_get_file(fix_relative(args->file, id), id ) ) return (string)strlen(s); }
4817401999-08-13Martin Nilsson  return rxml_error(tag, "Failed to find file", id); }
16509b1999-12-14Martin Nilsson array(string)|string tag_configimage(string t, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
16509b1999-12-14Martin Nilsson  if (!m->src) return rxml_error(t, "No src given", id);
4817401999-08-13Martin Nilsson 
692e711999-12-12Martin Nilsson  if (m->src[sizeof(m->src)-4..][0] == '.') m->src = m->src[..sizeof(m->src)-5];
4817401999-08-13Martin Nilsson  m->alt = m->alt || m->src;
692e711999-12-12Martin Nilsson  m->src = "/internal-roxen-" + m->src; m->border = m->border || "0";
4817401999-08-13Martin Nilsson 
ca6ea21999-10-03Johan Sundström  return ({ make_tag("img", m) });
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string tag_date(string q, mapping m, RequestID id)
4817401999-08-13Martin Nilsson { int t=(int)m["unix-time"] || time(1);
659d4b1999-10-18Martin Nilsson  t+=time_dequantifier(m);
4817401999-08-13Martin Nilsson  if(!(m->brief || m->time || m->date)) m->full=1;
659d4b1999-10-18Martin Nilsson  if(m->part=="second" || m->part=="beat") NOCACHE();
4817401999-08-13Martin Nilsson  else CACHE(60); // One minute is good enough.
bfd5fb1999-10-08Martin Nilsson  return tagtime(t, m, id, language);
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string|array(string) tag_insert( string tag, mapping m, RequestID id )
4817401999-08-13Martin Nilsson { string n;
5e63831999-10-04Johan Sundström  if(n = m->variable) { if(!id->variables[n]) return rxml_error(tag, "No such variable ("+n+").", id);
ecab8b2000-01-23Martin Nilsson  return m->quote=="none"?(string)id->variables[n]:({ html_encode_string((string)id->variables[n]) });
5e63831999-10-04Johan Sundström  }
4817401999-08-13Martin Nilsson 
bd2e111999-10-20Martin Nilsson  if(n = m->variables) { if(m->variables!="variables") return ({ html_encode_string(Array.map(indices(id->variables), lambda(string s, mapping m) { return sprintf("%s=%O\n", s, m[s]); }, id->variables) * "\n") });
5e63831999-10-04Johan Sundström  return ({ String.implode_nicely(indices(id->variables)) });
bd2e111999-10-20Martin Nilsson  }
4817401999-08-13Martin Nilsson 
98131d1999-10-08Martin Nilsson  if(n = m->other) {
f5132b1999-11-17Martin Nilsson  if(stringp(id->misc[n]) || intp(id->misc[n]))
e484171999-10-06Martin Nilsson  return m->quote=="none"?(string)id->misc[n]:({ html_encode_string((string)id->misc[n]) }); return rxml_error(tag, "No such other variable ("+n+").", id);
98131d1999-10-08Martin Nilsson  }
d93f831999-09-17Martin Nilsson 
5e63831999-10-04Johan Sundström  if(n = m->cookies)
4817401999-08-13Martin Nilsson  { NOCACHE();
bd2e111999-10-20Martin Nilsson  if(n!="cookies") return ({ html_encode_string(Array.map(indices(id->cookies), lambda(string s, mapping m) { return sprintf("%s=%O\n", s, m[s]); }, id->cookies) * "\n") });
5e63831999-10-04Johan Sundström  return ({ String.implode_nicely(indices(id->cookies)) });
4817401999-08-13Martin Nilsson  }
5e63831999-10-04Johan Sundström  if(n=m->cookie) {
4817401999-08-13Martin Nilsson  NOCACHE();
5e63831999-10-04Johan Sundström  if(id->cookies[n])
e484171999-10-06Martin Nilsson  return m->quote=="none"?id->cookies[n]:({ html_encode_string(id->cookies[n]) });
5e63831999-10-04Johan Sundström  return rxml_error(tag, "No such cookie ("+n+").", id);
4817401999-08-13Martin Nilsson  }
5e63831999-10-04Johan Sundström  if(m->file)
4817401999-08-13Martin Nilsson  { if(m->nocache) { int nocache=id->pragma["no-cache"]; id->pragma["no-cache"] = 1;
d059911999-10-08Martin Nilsson  n=API_read_file(id,m->file)||rxml_error("insert", "No such file ("+m->file+").", id);
4817401999-08-13Martin Nilsson  id->pragma["no-cache"] = nocache;
291e281999-08-16Martin Nilsson  return n;
4817401999-08-13Martin Nilsson  }
d059911999-10-08Martin Nilsson  return API_read_file(id,m->file)||rxml_error("insert", "No such file ("+m->file+").", id);
4817401999-08-13Martin Nilsson  } if(m->href && query("insert_href")) {
e161e41999-09-24Martin Nilsson  if(m->nocache) NOCACHE(); else CACHE(60);
16509b1999-12-14Martin Nilsson  Protocols.HTTP q=Protocols.HTTP.get_url(m->href);
e161e41999-09-24Martin Nilsson  if(q && q->status>0 && q->status<400)
5e63831999-10-04Johan Sundström  return ({ q->data() }); return rxml_error(tag, (q ? q->status_desc: "No server response"), id);
4817401999-08-13Martin Nilsson  }
c6481f2000-01-21Martin Nilsson  if(m->var) { object|array tagfunc=RXML.get_context()->tag_set->get_tag("!--#echo"); if(!tagfunc) return rxml_error(tag, "No SSI module added.", id); return ({ 1, "!--#echo", m});
f19d001999-12-18Martin Nilsson  }
4817401999-08-13Martin Nilsson  string ret="Could not fullfill your request.<br>\nArguments:"; foreach(indices(m), string tmp) ret+="<br />\n"+tmp+" : "+m[tmp];
5e63831999-10-04Johan Sundström 
4817401999-08-13Martin Nilsson  return rxml_error(tag, ret, id); }
ecab8b2000-01-23Martin Nilsson //FIXME: Broken.
9897451999-10-10Per Hedbor string|array(string) tag_configurl(string tag, mapping m, RequestID id)
5e63831999-10-04Johan Sundström {
bfd5fb1999-10-08Martin Nilsson  return ({ roxen->config_url() });
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string tag_return(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
bfd5fb1999-10-08Martin Nilsson  int c=(int)m->code; if(c) _error=c; string p=m->text; if(p) _rettext=p;
4817401999-08-13Martin Nilsson  return ""; }
9897451999-10-10Per Hedbor string tag_set_cookie(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
659d4b1999-10-18Martin Nilsson  if(!m->name)
4817401999-08-13Martin Nilsson  return rxml_error(tag, "Requires a name attribute.", id);
659d4b1999-10-18Martin Nilsson  string cookies = m->name+"="+http_encode_cookie(m->value||""); int t; //time
4817401999-08-13Martin Nilsson  if(m->persistent) t=(3600*(24*365*2)); else
659d4b1999-10-18Martin Nilsson  t=time_dequantifier(m);
4817401999-08-13Martin Nilsson 
659d4b1999-10-18Martin Nilsson  cookies += "; expires="+http_date(t+time(1));
4817401999-08-13Martin Nilsson 
b53b751999-10-09Martin Nilsson  //FIXME: Check the parameter's usability
4817401999-08-13Martin Nilsson  cookies += "; path=" +(m->path||"/");
bfd5fb1999-10-08Martin Nilsson  add_http_header(_extra_heads, "Set-Cookie", cookies);
4817401999-08-13Martin Nilsson  return ""; }
9897451999-10-10Per Hedbor string tag_remove_cookie(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
d93f831999-09-17Martin Nilsson  if(!m->name || !id->cookies[m->name]) return rxml_error(tag, "That cookie does not exists.", id);
bfd5fb1999-10-08Martin Nilsson  add_http_header(_extra_heads, "Set-Cookie", m->name+"="+http_encode_cookie(m->value||"")+"; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/" );
4817401999-08-13Martin Nilsson  return ""; }
16509b1999-12-14Martin Nilsson string tag_modified(string tag, mapping m, RequestID id, Stdio.File file)
4817401999-08-13Martin Nilsson {
659d4b1999-10-18Martin Nilsson  array (int) s;
16509b1999-12-14Martin Nilsson  Stdio.File f;
659d4b1999-10-18Martin Nilsson  if(m->by && !m->file && !m->realfile) { // FIXME: The auth module should probably not be used in this case. if(!id->conf->auth_module) return rxml_error(tag, "Modified by requires a user database.", id); // FIXME: The next row is defunct. last_modified_by does not exists. m->name = id->conf->last_modified_by(file, id); CACHE(10); return tag_user(tag, m, id, file); } if(m->file) { m->realfile = id->conf->real_file(fix_relative(m->file,id), id); m_delete(m, "file"); } if(m->by && m->realfile) { if(!id->conf->auth_module) return rxml_error(tag, "Modified by requires a user database.", id); if(f = open(m->realfile, "r")) { m->name = id->conf->last_modified_by(f, id); destruct(f); CACHE(10); return tag_user(tag, m, id, file); } return "A. Nonymous."; } if(m->realfile) s = file_stat(m->realfile); if(!(_stat || s) && !m->realfile && id->realfile) { m->realfile = id->realfile; return tag_modified(tag, m, id, file); } CACHE(10); if(!s) s = _stat; if(!s) s = id->conf->stat_file( id->not_query, id );
f5132b1999-11-17Martin Nilsson  if(s) {
659d4b1999-10-18Martin Nilsson  if(m->ssi)
c4d2a52000-01-03Martin Nilsson  return strftime(id->misc->ssi_timefmt || "%c", s[3]);
f5132b1999-11-17Martin Nilsson  return tagtime(s[3], m, id, language); }
659d4b1999-10-18Martin Nilsson 
c4d2a52000-01-03Martin Nilsson  if(m->ssi) return id->misc->ssi_errmsg||"";
659d4b1999-10-18Martin Nilsson  return rxml_error(tag, "Couldn't stat file.", id);
4817401999-08-13Martin Nilsson }
16509b1999-12-14Martin Nilsson string|array(string) tag_user(string tag, mapping m, RequestID id, Stdio.File file)
4817401999-08-13Martin Nilsson {
659d4b1999-10-18Martin Nilsson  string *u; string b, dom; if(!id->conf->auth_module) return rxml_error(tag, "Requires a user database.", id);
f5132b1999-11-17Martin Nilsson  if (!(b=m->name))
659d4b1999-10-18Martin Nilsson  return(tag_modified("modified", m | ([ "by":"by" ]), id, file)); b=m->name; dom=id->conf->query("Domain"); if(dom[-1]=='.') dom=dom[0..strlen(dom)-2]; if(!b) return ""; u=id->conf->userinfo(b, id); if(!u) return ""; if(m->realname && !m->email) { if(m->link && !m->nolink) return ({ "<a href=\"/~"+b+"/\">"+u[4]+"</a>" }); return ({ u[4] }); } if(m->email && !m->realname) { if(m->link && !m->nolink) return ({ sprintf("<a href=\"mailto:%s@%s@\">%s@%s</a>", b, dom, b, dom) }); return ({ b + "@" + dom }); } if(m->nolink && !m->link) return ({ sprintf("%s &lt;%s@%s&gt;", u[4], b, dom) }); return ({ sprintf("<a href=\"/~%s/\">%s</a> " "<a href=\"mailto:%s@%s\">&lt;%s@%s&gt;</a>", b, u[4], b, dom, b, dom) });
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor array(string) tag_set_max_cache( string tag, mapping m, RequestID id ) {
659d4b1999-10-18Martin Nilsson  id->misc->cacheable = (int)m->time;
9897451999-10-10Per Hedbor  return ({ "" }); }
4817401999-08-13Martin Nilsson  // ------------------- Containers ----------------
ecab8b2000-01-23Martin Nilsson array|string container_scope(string tag, mapping m,
9897451999-10-10Per Hedbor  string contents, RequestID id) {
ecab8b2000-01-23Martin Nilsson  if(!m->scope) { mapping old_variables = copy_value(id->variables); int truth=_ok; if (!m->extend) id->variables = ([]); contents = parse_rxml(contents, id); id->variables = old_variables; if (m->truth) _ok=truth; return ({ contents }); } return contents;
9897451999-10-10Per Hedbor } array(string) container_catch( string tag, mapping m, string c, RequestID id ) { string r; if(!id->misc->catcher_is_ready) id->misc+=(["catcher_is_ready":1]); else id->misc->catcher_is_ready++; array e = catch(r=parse_rxml(c, id)); id->misc->catcher_is_ready--;
f5132b1999-11-17Martin Nilsson  if(e) return e[0];
9897451999-10-10Per Hedbor  return ({r}); }
659d4b1999-10-18Martin Nilsson array(string) container_cache(string tag, mapping args,
9897451999-10-10Per Hedbor  string contents, RequestID id) { #define HASH(x) (x+id->not_query+id->query+id->realauth +id->conf->query("MyWorldLocation")) #if constant(Crypto.md5) object md5 = Crypto.md5(); md5->update(HASH(contents)); string key=md5->digest(); #else string key = (string)hash(HASH(contents)); #endif if(args->key) key += args->key; string parsed = cache_lookup("tag_cache", key); if(!parsed) { parsed = parse_rxml(contents, id); cache_set("tag_cache", key, parsed); } return ({parsed}); #undef HASH }
659d4b1999-10-18Martin Nilsson string|array(string) container_crypt( string s, mapping m,
9897451999-10-10Per Hedbor  string c, RequestID id ) {
f5132b1999-11-17Martin Nilsson  if(m->compare) return crypt(c,m->compare)?"<true>":"<false>"; return ({ crypt(c) });
9897451999-10-10Per Hedbor } string container_for(string t, mapping args, string c, RequestID id)
d059911999-10-08Martin Nilsson { string v = args->variable; int from = (int)args->from; int to = (int)args->to; int step = (int)args->step!=0?(int)args->step:(to<from?-1:1); if((to<from && step>0)||(to>from && step<0)) to=from+step; string res="";
659d4b1999-10-18Martin Nilsson  if(to<from)
9897451999-10-10Per Hedbor  {
b53b751999-10-09Martin Nilsson  if(v) for(int i=from; i>=to; i+=step) res += "<set variable="+v+" value="+i+">"+c; else for(int i=from; i>=to; i+=step) res+=c;
d059911999-10-08Martin Nilsson  return res; }
659d4b1999-10-18Martin Nilsson  else if(to>from)
9897451999-10-10Per Hedbor  {
b53b751999-10-09Martin Nilsson  if(v) for(int i=from; i<=to; i+=step) res += "<set variable="+v+" value="+i+">"+c; else for(int i=from; i<=to; i+=step) res+=c;
d059911999-10-08Martin Nilsson  return res; } return "<set variable="+v+" value="+to+">"+c; }
9897451999-10-10Per Hedbor string container_foreach(string t, mapping args, string c, RequestID id)
d059911999-10-08Martin Nilsson { string v = args->variable; array what; if(!args->in) return rxml_error(t, "No in attribute given.", id); if(args->variables) what = Array.map(args->in/"," - ({""}), lambda(string name, mapping v) { return v[name] || ""; }, id->variables); else what = Array.map(args->in / "," - ({""}), lambda(string var) { sscanf(var, "%*[ \t\n\r]%s", var); var = reverse(var); sscanf(var, "%*[ \t\n\r]%s", var); return reverse(var); });
659d4b1999-10-18Martin Nilsson 
d059911999-10-08Martin Nilsson  string res="";
659d4b1999-10-18Martin Nilsson  foreach(what, string w)
d059911999-10-08Martin Nilsson  res += "<set variable="+v+" value="+w+">"+c; return res; }
659d4b1999-10-18Martin Nilsson string container_apre(string tag, mapping m, string q, RequestID id)
4817401999-08-13Martin Nilsson { string href, s, *foo; if(!(href = m->href)) href=strip_prestate(strip_config(id->raw_url));
5e63831999-10-04Johan Sundström  else
4817401999-08-13Martin Nilsson  { if ((sizeof(foo = href / ":") > 1) && (sizeof(foo[0] / "/") == 1))
e484171999-10-06Martin Nilsson  return make_container("a", m, q);
d93f831999-09-17Martin Nilsson  href=strip_prestate(fix_relative(href, id));
4817401999-08-13Martin Nilsson  m_delete(m, "href"); }
659d4b1999-10-18Martin Nilsson 
4817401999-08-13Martin Nilsson  if(!strlen(href)) href=""; multiset prestate = (< @indices(id->prestate) >); if(m->add) { foreach((m->add-" ")/",", s) prestate[s]=1; m_delete(m,"add"); } if(m->drop) { foreach((m->drop-" ")/",", s) prestate[s]=0; m_delete(m,"drop"); } m->href = add_pre_state(href, prestate);
e484171999-10-06Martin Nilsson  return make_container("a", m, q);
4817401999-08-13Martin Nilsson }
659d4b1999-10-18Martin Nilsson string|array(string) container_aconf(string tag, mapping m,
9897451999-10-10Per Hedbor  string q, RequestID id)
4817401999-08-13Martin Nilsson { string href,s;
659d4b1999-10-18Martin Nilsson 
4817401999-08-13Martin Nilsson  if(!m->href) href=strip_prestate(strip_config(id->raw_url));
659d4b1999-10-18Martin Nilsson  else
4817401999-08-13Martin Nilsson  { href=m->href; if (search(href, ":") == search(href, "//")-1) return rxml_error(tag, "It is not possible to add configs to absolute URLs.", id); href=fix_relative(href, id); m_delete(m, "href"); }
ebdb652000-01-14Martin Nilsson  array cookies = ({});
4817401999-08-13Martin Nilsson  if(m->add) { foreach((m->add-" ")/",", s)
ebdb652000-01-14Martin Nilsson  cookies+=({s});
4817401999-08-13Martin Nilsson  m_delete(m,"add"); } if(m->drop) { foreach((m->drop-" ")/",", s)
ebdb652000-01-14Martin Nilsson  cookies+=({"-"+s});
4817401999-08-13Martin Nilsson  m_delete(m,"drop"); }
ebdb652000-01-14Martin Nilsson  m->href = add_config(href, cookies, id->prestate);
e484171999-10-06Martin Nilsson  return make_container("a", m, q);
4817401999-08-13Martin Nilsson }
659d4b1999-10-18Martin Nilsson string container_maketag(string tag, mapping m, string cont, RequestID id)
9897451999-10-10Per Hedbor {
5d93971999-10-04Martin Nilsson  mapping args=(!m->noxml&&m->type=="tag"?(["/":"/"]):([]));
0a22e01999-10-04Martin Nilsson  cont=parse_html(parse_rxml(cont,id), ([]), (["attrib":
ecab8b2000-01-23Martin Nilsson  lambda(string tag, mapping m, string cont, mapping args) { args[m->name]=cont;
4817401999-08-13Martin Nilsson  return ""; }
ecab8b2000-01-23Martin Nilsson  ]), args);
18be8a1999-08-17Martin Nilsson  if(m->type=="container")
5d93971999-10-04Martin Nilsson  return make_container(m->name, args, cont); return make_tag(m->name, args);
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string container_doc(string tag, mapping m, string s)
4817401999-08-13Martin Nilsson { if(!m["quote"])
d93f831999-09-17Martin Nilsson  if(m["pre"]) { m_delete(m,"pre"); return "\n"+make_container("pre",m, replace(s, ({"{","}","& "}),({"&lt;","&gt;","&amp; "})))+"\n"; }
4817401999-08-13Martin Nilsson  else return replace(s, ({ "{", "}", "& " }), ({ "&lt;", "&gt;", "&amp; " }));
659d4b1999-10-18Martin Nilsson  else
d93f831999-09-17Martin Nilsson  if(m["pre"]) { m_delete(m,"pre"); m_delete(m,"quote"); return "\n"+make_container("pre",m, replace(s, ({"<",">","& "}),({"&lt;","&gt;","&amp; "})))+"\n"; }
4817401999-08-13Martin Nilsson  else return replace(s, ({ "<", ">", "& " }), ({ "&lt;", "&gt;", "&amp; " })); }
9897451999-10-10Per Hedbor string container_autoformat(string tag, mapping m, string s, RequestID id)
4817401999-08-13Martin Nilsson { s-="\r";
b53b751999-10-09Martin Nilsson  string p=(m["class"]?"<p class=\""+m["class"]+"\">":"<p>");
d93f831999-09-17Martin Nilsson 
4817401999-08-13Martin Nilsson  if(!m->nobr) { s = replace(s, "\n", "<br>\n"); if(m->p) {
d93f831999-09-17Martin Nilsson  if(search(s, "<br>\n<br>\n")!=-1) s=p+s; s = replace(s, "<br>\n<br>\n", "\n</p>"+p+"\n");
d614691999-08-16Martin Nilsson  if(sizeof(s)>3 && s[0..2]!="<p>" && s[0..2]!="<p ")
d93f831999-09-17Martin Nilsson  s=p+s; if(s[..sizeof(s)-4]==p)
4817401999-08-13Martin Nilsson  return s[..sizeof(s)-4]; else return s+"</p>"; } return s; } if(m->p) {
d93f831999-09-17Martin Nilsson  if(search(s, "\n\n")!=-1) s=p+s; s = replace(s, "\n\n", "\n</p>"+p+"\n");
d614691999-08-16Martin Nilsson  if(sizeof(s)>3 && s[0..2]!="<p>" && s[0..2]!="<p ")
d93f831999-09-17Martin Nilsson  s=p+s; if(s[..sizeof(s)-4]==p)
4817401999-08-13Martin Nilsson  return s[..sizeof(s)-4]; else return s+"</p>"; }
659d4b1999-10-18Martin Nilsson 
4817401999-08-13Martin Nilsson  return s; }
8859351999-11-25Martin Nilsson class Smallcapsstr {
d93f831999-09-17Martin Nilsson  constant UNDEF=0, BIG=1, SMALL=2; static string text="",part="",bigtag,smalltag; static mapping bigarg,smallarg; static int last=UNDEF; void create(string bs, string ss, mapping bm, mapping sm) { bigtag=bs; smalltag=ss; bigarg=bm; smallarg=sm; }
8859351999-11-25Martin Nilsson  string _sprintf() { return "Smallcapsstr()"; }
d93f831999-09-17Martin Nilsson  void add(string char) { part+=char; } void add_big(string char) { if(last!=BIG) flush_part(); part+=char; last=BIG; } void add_small(string char) { if(last!=SMALL) flush_part(); part+=char; last=SMALL; } void write(string txt) { if(last!=UNDEF) flush_part(); part+=txt; } void flush_part() { switch(last){ case UNDEF: default: text+=part; break; case BIG: text+=make_container(bigtag,bigarg,part); break; case SMALL: text+=make_container(smalltag,smallarg,part); break; } part=""; last=UNDEF; } string value() { if(last!=UNDEF) flush_part();
659d4b1999-10-18Martin Nilsson  return text;
d93f831999-09-17Martin Nilsson  } }
9897451999-10-10Per Hedbor string container_smallcaps(string t, mapping m, string s)
4817401999-08-13Martin Nilsson {
16509b1999-12-14Martin Nilsson  Smallcapsstr ret;
d93f831999-09-17Martin Nilsson  string spc=m->space?"&nbsp;":""; m_delete(m, "space"); mapping bm=([]), sm=([]); if(m["class"] || m->bigclass) { bm=(["class":(m->bigclass||m["class"])]); m_delete(m, "bigclass"); } if(m["class"] || m->smallclass) { sm=(["class":(m->smallclass||m["class"])]); m_delete(m, "smallclass"); } if(m->size) { bm+=(["size":m->size]); if(m->size[0]=='+' && (int)m->size>1) sm+=(["size":m->small||"+"+((int)m->size-1)]); else sm+=(["size":m->small||(string)((int)m->size-1)]); m_delete(m, "small");
8859351999-11-25Martin Nilsson  ret=Smallcapsstr("font","font", m+bm, m+sm);
d93f831999-09-17Martin Nilsson  }
f5132b1999-11-17Martin Nilsson  else
8859351999-11-25Martin Nilsson  ret=Smallcapsstr("big","small", m+bm, m+sm);
d93f831999-09-17Martin Nilsson  for(int i=0; i<strlen(s); i++) if(s[i]=='<') { int j; for(j=i; j<strlen(s) && s[j]!='>'; j++); ret->write(s[i..j]); i+=j-1;
4817401999-08-13Martin Nilsson  }
d93f831999-09-17Martin Nilsson  else if(s[i]<=32) ret->add_small(s[i..i]); else if(lower_case(s[i..i])==s[i..i]) ret->add_small(upper_case(s[i..i])+spc); else if(upper_case(s[i..i])==s[i..i]) ret->add_big(s[i..i]+spc); else ret->add(s[i..i]+spc); return ret->value();
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string container_random(string tag, mapping m, string s)
4817401999-08-13Martin Nilsson {
16509b1999-12-14Martin Nilsson  string|array q;
f5132b1999-11-17Martin Nilsson  if(!(q=m->separator || m->sep)) return (q=s/"\n")[random(sizeof(q))]; return (q=s/q)[random(sizeof(q))];
4817401999-08-13Martin Nilsson }
659d4b1999-10-18Martin Nilsson array(string) container_formoutput(string tag_name, mapping args,
9897451999-10-10Per Hedbor  string contents, RequestID id)
4817401999-08-13Martin Nilsson {
e484171999-10-06Martin Nilsson  return ({ do_output_tag( args, ({ id->variables }), contents, id ) });
4817401999-08-13Martin Nilsson }
16509b1999-12-14Martin Nilsson array(string) container_gauge(string t, mapping args, string contents, RequestID id)
4817401999-08-13Martin Nilsson { NOCACHE(); int t = gethrtime(); contents = parse_rxml( contents, id ); t = gethrtime()-t; string define = args->define?args->define:"gauge";
16509b1999-12-14Martin Nilsson  if(args->silent) return ({ "" }); if(args->timeonly) return ({ sprintf("%3.6f", t/1000000.0) });
4817401999-08-13Martin Nilsson  if(args->resultonly) return ({contents});
e484171999-10-06Martin Nilsson  return ({ "<br><font size=\"-1\"><b>Time: "+
4817401999-08-13Martin Nilsson  sprintf("%3.6f", t/1000000.0)+
e484171999-10-06Martin Nilsson  " seconds</b></font><br>"+contents });
659d4b1999-10-18Martin Nilsson }
4817401999-08-13Martin Nilsson  // Removes empty lines
16509b1999-12-14Martin Nilsson array(string) container_trimlines( string tag_name, mapping args,
9897451999-10-10Per Hedbor  string contents, RequestID id )
4817401999-08-13Martin Nilsson {
9897451999-10-10Per Hedbor  contents = replace(parse_rxml(contents,id), ({"\r\n","\r" }), ({"\n","\n"}));
4817401999-08-13Martin Nilsson  return ({ (contents / "\n" - ({ "" })) * "\n" }); }
659d4b1999-10-18Martin Nilsson void container_throw( string t, mapping m, string c, RequestID id) {
3a4b9a1999-12-27Martin Nilsson  if(!id->misc->catcher_is_ready && c[-1]!='\n')
9897451999-10-10Per Hedbor  c+="\n";
659d4b1999-10-18Martin Nilsson  throw( ({ c, backtrace() }) );
9897451999-10-10Per Hedbor }
f5132b1999-11-17Martin Nilsson // Internal methods for the default tag private int|array internal_tag_input(string t, mapping m, string name, multiset(string) value)
4817401999-08-13Martin Nilsson {
f5132b1999-11-17Martin Nilsson  if (name && m->name!=name) return 0; if (m->type!="checkbox" && m->type!="radio") return 0; if (value[m->value||"on"]) { if (m->checked) return 0; m->checked = "checked"; } else { if (!m->checked) return 0; m_delete(m, "checked" ); }
4817401999-08-13Martin Nilsson 
f5132b1999-11-17Martin Nilsson  return ({ make_tag(t, m) });
4817401999-08-13Martin Nilsson }
8859351999-11-25Martin Nilsson array split_on_option( string what, Regexp r ) { array a = r->split( what ); if( !a ) return ({ what }); return split_on_option( a[0], r ) + a[1..]; }
f5132b1999-11-17Martin Nilsson private int|array internal_tag_select(string t, mapping m, string c, string name, multiset(string) value)
4817401999-08-13Martin Nilsson {
8859351999-11-25Martin Nilsson  if(m->name!=name) return ({ make_container(t,m,c) }); Regexp r = Regexp( "(.*)<([Oo][Pp][Tt][Ii][Oo][Nn])([^>]*)>(.*)" ); array(string) tmp=split_on_option(c,r); string ret=tmp[0],nvalue; int selected,stop; tmp=tmp[1..]; while(sizeof(tmp)>2) { stop=search(tmp[2],"<"); if(sscanf(lower_case(tmp[1]),"%*svalue=%s%*[ >]",nvalue)!=3) nvalue=tmp[2][..stop==-1?sizeof(tmp[2]):stop]; selected=Regexp(".*[Ss][Ee][Ll][Ee][Cc][Tt][Ee][Dd].*")->match(tmp[1]); ret+="<"+tmp[0]+tmp[1]; if(value[nvalue] && !selected) ret+=" selected=\"selected\""; ret+=">"+tmp[2]; if(!Regexp(".*</[Oo][Pp][Tt][Ii][Oo][Nn]")->match(tmp[2])) ret+="</"+tmp[0]+">"; tmp=tmp[3..]; } return ({ make_container(t,m,ret) });
4817401999-08-13Martin Nilsson }
f5132b1999-11-17Martin Nilsson array(string) container_default( string t, mapping m, string c, RequestID id)
4817401999-08-13Martin Nilsson {
f5132b1999-11-17Martin Nilsson  multiset value=(<>); if(m->value) value=mkmultiset((m->value||"")/(m->separator||",")); if(m->variable) value+=mkmultiset(({id->variables[m->variable]})); c = parse_rxml(c, id ); if(value==(<>)) return ({c}); return ({ parse_html(c, (["input":internal_tag_input]), (["select":internal_tag_select]), m->name, value) });
4817401999-08-13Martin Nilsson }
9897451999-10-10Per Hedbor string container_sort(string t, mapping m, string c, RequestID id)
4817401999-08-13Martin Nilsson { if(!m->separator) m->separator = "\n"; string pre="", post=""; array lines = c/m->separator; while(lines[0] == "") { pre += m->separator; lines = lines[1..]; } while(lines[-1] == "") { post += m->separator; lines = lines[..sizeof(lines)-2]; } lines=sort(lines); return pre + (m->reverse?reverse(lines):lines)*m->separator + post; }
16509b1999-12-14Martin Nilsson array(string)|string container_recursive_output (string tagname, mapping args,
9897451999-10-10Per Hedbor  string contents, RequestID id)
4817401999-08-13Martin Nilsson { int limit; array(string) inside, outside;
659d4b1999-10-18Martin Nilsson  if (id->misc->recout_limit)
9897451999-10-10Per Hedbor  {
4817401999-08-13Martin Nilsson  limit = id->misc->recout_limit - 1; inside = id->misc->recout_outside, outside = id->misc->recout_inside; }
659d4b1999-10-18Martin Nilsson  else
9897451999-10-10Per Hedbor  {
4817401999-08-13Martin Nilsson  limit = (int) args->limit || 100; inside = args->inside ? args->inside / (args->separator || ",") : ({}); outside = args->outside ? args->outside / (args->separator || ",") : ({}); if (sizeof (inside) != sizeof (outside))
16509b1999-12-14Martin Nilsson  return rxml_error(tagname, "'inside' and 'outside' replacement sequences " "aren't of same length", id);
4817401999-08-13Martin Nilsson  } if (limit <= 0) return contents; int save_limit = id->misc->recout_limit; string save_inside = id->misc->recout_inside, save_outside = id->misc->recout_outside; id->misc->recout_limit = limit; id->misc->recout_inside = inside; id->misc->recout_outside = outside; string res = parse_rxml ( parse_html ( contents,
659d4b1999-10-18Martin Nilsson  (["recurse": lambda (string t, mapping a, string c) {return ({c});}]),
9897451999-10-10Per Hedbor  ([]),
659d4b1999-10-18Martin Nilsson  "<" + tagname + ">" + replace (contents, inside, outside) +
9897451999-10-10Per Hedbor  "</" + tagname + ">"),
4817401999-08-13Martin Nilsson  id); id->misc->recout_limit = save_limit; id->misc->recout_inside = save_inside; id->misc->recout_outside = save_outside; return ({res}); }
bd2e111999-10-20Martin Nilsson //I'll donate a Star Wars insiders guide to the //first one to figure out what this number means, //and how it was calculated. nilsson@idonex.se #define MAGIC_EXIT 4921325
9897451999-10-10Per Hedbor string tag_leave(string tag, mapping m, RequestID id)
4817401999-08-13Martin Nilsson {
659d4b1999-10-18Martin Nilsson  if(id->misc->leave_repeat)
9897451999-10-10Per Hedbor  {
4817401999-08-13Martin Nilsson  id->misc->leave_repeat--;
bd2e111999-10-20Martin Nilsson  throw(MAGIC_EXIT);
4817401999-08-13Martin Nilsson  } return rxml_error(tag, "Must be contained by &lt;repeat&gt;.", id); }
9897451999-10-10Per Hedbor string container_repeat(string tag, mapping m, string c, RequestID id)
4817401999-08-13Martin Nilsson { if(!id->misc->leave_repeat) id->misc->leave_repeat=0; int exit=id->misc->leave_repeat++,loop,maxloop=(int)m->maxloops||10000; string ret="",iter; while(loop<maxloop && id->misc->leave_repeat!=exit) { loop++; mixed error=catch { iter=parse_rxml(c,id); };
bd2e111999-10-20Martin Nilsson  if((intp(error) && error!=0 && error!=MAGIC_EXIT) || !intp(error))
4817401999-08-13Martin Nilsson  throw(error); if(id->misc->leave_repeat!=exit) ret+=iter; } if(loop==maxloop) return ret+rxml_error(tag, "Too many iterations ("+maxloop+").", id); return ret; }
659d4b1999-10-18Martin Nilsson string container_replace( string tag, mapping m, string cont, RequestID id)
9897451999-10-10Per Hedbor {
659d4b1999-10-18Martin Nilsson  switch(m->type)
9897451999-10-10Per Hedbor  {
4817401999-08-13Martin Nilsson  case "word": default: if(!m->from) return cont;
9897451999-10-10Per Hedbor  return replace(cont,m->from,(m->to?m->to:""));
4817401999-08-13Martin Nilsson  case "words": if(!m->from) return cont; string s=m->separator?m->separator:","; array from=(array)(m->from/s); array to=(array)(m->to/s); int balance=sizeof(from)-sizeof(to); if(balance>0) to+=allocate(balance,""); return replace(cont,from,to); } }
9897451999-10-10Per Hedbor array(string) container_cset( string t, mapping m, string c, RequestID id )
4817401999-08-13Martin Nilsson {
31e39c1999-10-10Per Hedbor  if( m->quote != "none" ) c = html_decode_string( c );
9897451999-10-10Per Hedbor  if( !m->variable ) return ({rxml_error(t, "Variable not specified.", id)}); id->variables[ m->variable ] = c; return ({ "" });
4817401999-08-13Martin Nilsson }
bd2e111999-10-20Martin Nilsson // ----------------- If registration stuff --------------
4817401999-08-13Martin Nilsson  mapping query_if_callers() { return ([
bd2e111999-10-20Martin Nilsson  "expr":lambda( string q){ return (int)sexpr_eval(q); }
4817401999-08-13Martin Nilsson  ]); }
659d4b1999-10-18Martin Nilsson  // ---------------- API registration stuff ---------------
16509b1999-12-14Martin Nilsson string api_query_modified(RequestID id, string f, int|void by)
659d4b1999-10-18Martin Nilsson { mapping m = ([ "by":by, "file":f ]); return tag_modified("modified", m, id, id); }