Documention for: lds-local.r Created by: sunanda on: 20-Jan-2004 Last updated by: sunanda on: 2-Mar-2006 Format: text/editable Downloaded on: 30-Apr-2025 [numbering-on [contents [asis Version: 0.0.8 31-Jan-2006 Sunanda asis] [div/style/border:blue+thin+solid [h2 History [h3 2-Mar-2006 -- 0.0.8 [li **script-search** request added to search the Script library for matching words. [li Some typos corrected. list] [h3 28-Jan-2006 -- 0.0.7 [li **rss-get-feed-data** request added to supply the data available in the RSS feed. list] [h3 9-Feb-2005 -- 0.0.6 [li Add request for the Mailing list search feature: **get-rml-status** [li Ditto for **search-rml**. list] [h3 8-Sep-2004 -- 0.0.5 [li Package update requests added. You can now use LDS to write a client to upload and update packages. [li get-script-documentation added. You can now download any documentation for a script list] [h3 9-Jul-2004 -- 0.0.4 [li **latest** option added to get-rml-message to get the latest message without having to know its message number. [li token support added for verified requests [li contribute-script request added -- you can add or update your scripts using LDS. list] [h3 28-Apr-2004 -- 0.0.3 Archive version requests added: [li get-archive-version [li list-archive-versions list] Extra fields added to **list-package-header** to support installation folders and better download information [h3 19-Jan-2004 -- 0.0.1 Initial version [h3 20-Feb-2004 -- 0.0.2 Package handling requests added: [li get-package-file [li list-package-header list] div] [br [div/style/border:green+thin+solid [h2 Overview Library Data Services (LDS) is an interface to the REBOL.org website that lets any REBOL program retrieve data from the Library in a REBOL format. Example: get the list of Library members [asis probe lds/send-server 'get-user-list [] make object! [ status: [0 0 ""] data: make object! [ user-list: ["gregg" "volker" "sunanda"] ] ] asis] What comes back is a REBOL object with just two fields: [li status - contains any error information if the request failed [li data - another object, containing the data you requested. The format of this depends on the request, and in some cases, the data available. List] div] [br [div/style/border:yellow+thin+solid [h2 Uses You could use this interface to: [li Download messages -- such as all messages from one poster -- into a personal message archive [li Write a few lines of code to perform more complex searches on the Library scripts [li Update the scripts you own List] div] [br [div/style/border:red+thin+solid [h2 Levels of access LDS defines three levels of access: [li Public [li Member [li Owner list] [h3 Public Broadly, any data you can retrieve via a web browser while not logged on: [li Lists of Library member names [li Download a script [li Download all or part of the Mailing List archive [li Find scripts that match various criteria list] [h3 Member Things you can do as a member of the Library: [li View extended member and script details [li Contribute a new script List] [h3 Owner Things you can do as the owner of a script: [li Update a script with a new version [li View a script's statistics List] div] [br [div/style/border:blue+thin+solid [h2 Installing Library Data Services [p Run it directly from the REBOL.org server: [p/class/notice do http://www.rebol.org/library/public/lds-local.r [p That's all it takes. div] [br [div/style/border:green+thin+solid [h2 Using Library Data Services [h3 Initialising the interface [p Issue this call once before you call the service: [p/class/notice do http://www.rebol.org/library/public/lds-local.r [h3 Calling the interface All calls have the same format: [p/class/notice response-data: lds/send-server 'request [parameters] [li request: the request you want -- eg **get-user-list** or **help** [li parameters: any additional data needed for the request. Example, [li get-script requires a script name. If there are no parameters for a request, specify as **none** or **[]** [li response-data is the reply back from the server. It is an object! with two operational fields: [list [li status: a block with three error/status fields (see next section) [li data: an object! or 'none. It will be 'none if there is an error, otherwise it will be an object that contain the results of your request. list] list] [h3 Calling the interface with a token [p A Library token is needed if you are doing something at the Member or Owner level. [p Getting a token is explained later (see Library Tokens). [p A call using a token looks like this: [p/class/notice response-data: lds/send-server/use-token 'request [parameters] div] [br [div/style/border:yellow+thin+solid [h2 Status reply LDS always replies with values in the Status field. It is a block with three parts: [li status/1-- major error code [li status/2-- further status information [li status/3-- short english text describing the error List] [h3 Status/1 An integer! between 000 - 999. The values are divided into specific ranges: [li 000- the request worked [li 001 - 099- reserved [li 100 - 199 - a problem with the URL. Almost certainly a bug in lds/send-server [li 200 - 299 - a formatting problem with the parameter (eg you have supplied a string! for a request that expects an integer!) [li 300 - 399 - a contextual problem with the parameter (eg you have supplied the name of a script that does not exist) [li 400 - 499- communication problem. [li 500 - 799 - reserved [li 800 - 899 - authorisation error: the request requires a valid Library member name and password. [li 900 - 999 - internal problem: error in LDS. Congratulations! You've just crashed the server-side of LDS. Please tell me what you did! list] [h3 Status/2 May contain context-sensitive information. For example, if the status/3 text is "script not found", status/2 may contain the script name we were looking for. Not all requests support this. [h3 Status/3 A short text, in english, describing the problem. [h3 Examples [asis probe lds/send-server 'list-updated-scripts ["zzzzz"] make object! [ status: [200 0 "non-integer days"] data: none ] asis] (zzzzz should be an integer) [asis probe lds/send-server 'get-script ["xxxx.r"] make object! [ status: [300 0 "unknown script"] data: none ] asis] (xxxx.r is not a script in the Library) [asis probe lds/send-server 'get-script ["sssss.r"] make object! [ status: [400 0 "can't connect"] data: none ] asis] (You may be offline) div] [br [div/style/border:red+thin+solid [h2 Library tokens [p To use some LDS requests, you must be a member of the Library. [p If you are not a member of the Library, you can join by going here: [p http://www.rebol.org/cgi-bin/cgiwrap/rebol/signup.r [p LDS needs you to supply a Library token on each call. This identifies who you are in much the same way that a cookie does when you visit the Library using the web interface. [h3 Getting a token [p Log on, and visit this page: [p http://www.rebol.org/cgi-bin/cgiwrap/rebol/lds-library-tokens.r [p Tell it how many tokens you want (one is normally enough -- see multiple tokens below for why you may want more than one) and click "send me tokens". [p The tokens will be emailed to your registered address. [h3 Install the token [p A token looks something like this: [asis #{00C04C0913E76ECFF780DD73} asis] [p Save it as a text file called **lds-library-token.txt** in the folder from which you execute Library Data services, eg: [asis write %lds-library-token.txt mold #{00C04C0913E76ECFF780DD73} asis] [p The token is now ready for use. [h3 Using the token [p Add the /use-token refinement to each lds/send-server request, eg: [p/class/notice Response-object: lds/send-server/user-token 'token-test ["test my token"] [li LDS will need security permission to both read and **write** %lds-library-token.txt -- the token is updated on each successful usage. [li You can add /use-token to any request, but it is only needed for requests that are marked as needing it. List] [h3 Multiple tokens [p If you use LDS from more than one location (perhaps on different machines) you need a different token for each location. You can have as many tokens as you want. div] [br [div/style/border:blue+thin+solid [h2 General Library requests [h3 help [p Returns a list of all LDS requests and some help on each of them -- a good way to see if you have an out-of-date copy of these notes. [li Parameters: none [li Response: request-list [block!] [list [li Request list is a block with paired values. [li The first is the name of a request [li the second is an object with details of the request. Details include: [list [li authorisation? -- true if request requires a userid and password [li purpose -- what the request does [li parameters -- what parameters the request needs [li response -- what the response is List] List] List] [h4 Example [asis probe lds/send-server 'help none make object! [ status: [0 0 ""] data: make object! [ request-list: [ "get-rml-message" make object! [ authorisation?: false purpose: {Retrieve a message from the REBOL Mailing list archive} parameters: "Msgid [integer!]" response: "Object containing message and control headers" ] "get-script" make object! [ [snip] asis] [h3 list-users [p Retrieve list of activated Library members [li Parameters: none [li Response: user-list [] List] [p ("activated" means they have logged on at least once) [h4 Example [asis probe lds/send-server 'list-users [] make object! [ status: [0 0 ""] data: make object! [ user-list: ["volker" "gregg" "sunanda"] ] ] Asis] div] [br [div/style/border:green+thin+solid [h2 Mailing List requests [p Use these requests to read messages from the Mailing list archive [h3 get-rml-message [p Retrieve a message from the REBOL Mailing list archive [li Parameters: Msgid [integer! | string!] [li Response: Object! -- containing message and control headers List] [h4 Example 1 -- get a single message [asis probe res: lds/send-server 'get-rml-message [237859] asis] The fields in the data object for this request are: [li msgid -- Library Archive identifier for this message. (The Library has two formats for the message id: a number, which is broadly compatible with the message numbers in other archives of the ML, and a code that isn't. Either will work. These two requests return the same message: [list [li probe res: lds/send-server 'get-rml-message [237859] [li probe res: lds/send-server 'get-rml-message ["CKLQ"] list] [li author -- slightly munged email address [li msgdate -- local date and time of posting. Will usually be a REBOL date!, but may sometimes be a REBOL date! in a string. Use **load form data/msgdate** to coerce to date! [li subject -- subject line [li links -- msgids of: first-in-thread / next-in-thread / previous-in-thread [li a-links -- msgids of: first-for-author / next-for-author / previous-for-author [li thread -- If message is the first in a thread, msgids of: first-in-previous thread / first-in-next-thread [li content: -- message text list] [h4 Example 2 -- get all messages for a given thread [asis msgs: copy [] res: lds/send-server 'get-rml-message [213498] forever [ append msgs res/data if res/data/links/3 = 0 [break] ;; no next-in-thread link res: lds/send-server 'get-rml-message reduce [res/data/links/3] ] print ["There were" length? msgs "message(s) in the thread"] asis] [h4 Example 3 -- get the latest message [asis msgs: copy [] res: lds/send-server 'get-rml-message ["latest"] asis] [h3 get-rml-status [p Sends you back some status information about the Mailing list archive. [li Parameters: None [li Response: Object! -- containing various counts -- see example List] [h4 Example [asis probe res: lds/send-server 'get-rml-status [] make object! [ status: [0 0 ""] data: make object! [ counts: [241337 241337] threads: [8706] years: [1980 2000 2001 2002 2003 2004 2005 2024] ] asis] The fields in the data object for this request are: [li counts block [list [li count/1 -- total messages in the Archive [li count/2 -- total messages that are in the word index (ie that you can search on). This number may often be a little lower than count/1: indexing is an async process and lags behind at times. If it is significantly lower, then we may be rebuilding the word index. If so, please be patient [li count/3 -- and higher: reserved. we may be adding them later, so don't assume that count/1 = last count list] [li threads block -- Thread information. Currently a block with just 1 number: the total number of threads. But we may add more numbers, so (as above) don't assume that thread/1 = last thread [li years block -- information about the years we have indexed. Use this with the search-rml request. Note that there maybe more years (as shown in the example) than you might expect. See search-rml for more details. list] [p get-rml-status is most useful for getting the full span of years for a **search-rml** request....See immediately below. [h3 search-rml [p Sends you back the message ids for all threads that meet your search criteria [li Parameters: A string that has both the words on which you want to search and, optionally, the years you want to search -- see below [li Response: Object! -- containing various fields -- see below List] [h4 Parameter [p The parameter is a single quoted string. It should contain at least one word on which you want to search. It may also contain one or more years. [li If the string does not contain any years, the search will be on the subject lines of **all** posts [li If the string does contain one or more years, the search will be on the **full text** of the posts for those years list] [h4 Examples of the search parameter: [li ""help"" -- searches for ""help"" in all subject lines [li ""help 2005 2004"" -- searches for ""help"" in the full text of all posts whose thread begin in 2004 or 2005 [li ""2001 bunny 2003" -- searches for the word ""bunny"" in all posts for 2001 and 2003 (yes, there is one result) [li ""2000 white pink 2001 apple 2002 2003"" -- searches for posts containing all the words ""white pink apple"" in the years 2000 through 2003 (and, yes, expect one result) list] [li ""async version"" -- searches the subject lines for the two words. list] [h4 Response object [p Contains both the message ids of the messages that matched your search, and some reflected back fields to confirm what has been searched. [p An example is [asis make object! [ status: [0 0 ""] data: make object! [ target-words: [""apple"" ""pink"" ""white""] search-type: "posts" span: [2003 2002 2001 2000] msgids: [207276] ] ] asis] [li target-words -- the words searched were ""apple"" AND ""pink"" AND ""white"". If your original request contained other words, they have been ignored as they are on the **stop list** [li search-type -- the search type was **posts** meaning we checked the whole of all the posts. The other possibility is **subjects**, meaning we searched just the subject lines. [li span -- we searched the years 2000 through 2003 [li msgids -- we found one thread meeting the search criteria. 207276 is the message id of the first message in that thread list] [h4 Searchable years [p/class/notice/style/font-style:italic Using the **search-rml** request, you can search on **all** years for which threads exist. This includes some strange ones, such as 1980 and 2024. They exist because we take the **date** field in the original email's header as correct. and, obviously, in some cases they were not: the sender's ISP or server was badly set up. [p/class/*/style/* We don't have much choice about that. The Mailing list archive started some years after the Mailing list, so we don't have accurate context information to correct the problem. [h3 Examples [asis probe lds/send-server 'search-rml ["async version"] make object! [ status: [0 0 ""] data: make object! [ target-words: ["async" "version"] search-type: "subjects" msgids: [234122] ] ] asis] [asis probe lds/send-server 'search-rml ["1960 1961 help me to get a good job 2004 2003"] make object! [ status: [0 0 ""] data: make object! [ target-words: ["get" "good" "help" "job" "me"] search-type: "posts" span: [2004 2003] msgids: [230329 230451 ....snipped .....] ] ] asis] [p Note that the span contains only the years we could search (we don't have messages from the 1960s), and the target-words does not include the stop words ""to"" and ""a"". div] [br [div/style/border:yellow+thin+solid [h2 Script requests [p Use these requests to search the Script Library, and to download scripts. [h3 get-script [p Retrieve latest version of a script [li Parameters: script name [string!] [li Response: script [string!] list] [p Returns the source of the named script [h4 Example: [asis probe lds/send-server 'get-script ["wumpus.r"] make object! [ status: [0 0 ""] data: make object! [ script: {REBOL[ Title: "Hunt the Wumpus" Date: 20-Jul-2003 File:^- %wumpus.r Purpose: "A REBOL version of a retro text game. Just for fun." Author: "Gregg Irwin" EMail: greggirwin@acm.org Version: 1.0.1 Library: [ level: 'intermediate platform: 'all [snip] asis] [h4 Note to script owners [p If you own a script, and check its download count on the **statistics page** of REBOL.org: LDS get-script downloads are counted as "Total LDS downloads". [h3 list-scripts-by-filter [p Returns a list of script names that match the search filter. [li Parameters: search filter and value, eg type-demo or domain-cgi [li Response: script-list [block] list] [h4 Example [asis probe lds/send-server 'list-scripts-by-filter [domain-xml] make object! [ status: [0 0 ""] data: make object! [ script-list: ["json.r" "xmlgen.r" "rblxelparser.r"] ] ] asis] [h3 list-search-filters [p Returns an object with all the possible filters that can be used with list-scripts-by-filter [li Parameters: none [li Response: object! list] [p The response object has a series of blocks, each represents a possible set of filters, for example [p/class/notice type: [article demo dialect faq function ... ] [p means you can filter on type-article type-demo etc [h3 search-scripts [p Returns a list of script names that contain the words you asked for [li Parameters: string containing the target words [li Response: script-list [block] list] [h4 Example [asis probe lds/send-server 'search-scripts ["decompress"] make object! [ status: [0 0 ""] data: make object! [ script-list: ["compress.r" "autoextract.r"] ] ] asis] [p The script-list returned is in script relevance order: best matches first. [h3 list-scripts-owned-by [p Returns a list of scripts owned by a given Library member [li Parameters: owner-name [string!] [li Response: script-list [block!] list] [p If the owner name is not recognised, the script-list is returned as an empty block. [h4 Example -- get list of scripts owned by Sunanda [asis probe lds/send-server 'list-scripts-owned-by ["sunanda"] make object! [ status: [0 0 ""] data: make object! [ script-list: ["cookie-example.r" "oneliner-chess-board.r" "oneliner-monty-hall.r"] asis] [h3 list-updated-scripts [p Get a list of new or updated scripts in the last [n] days [li Parameters: n [integer!] [li Response: script-list [block!] list] [p Lets you find which scripts have been added or updated in the last n days. "n" is an integer: 1 or more [h4 Example 1: what's new in the last 15 days? [asis probe lds/send-server 'list-updated-scripts [15] make object! [ status: [0 0 ""] data: make object! [ script-list: ["mtv.r" "mvt.r" "mvs.r"] ] ] asis] [h4 Example 2: Download new versions of scripts changed in the last 31 days [asis res1: lds/send-server 'list-updated-scripts [31] foreach scr res1/data/script-list [ res2: lds/send-server 'get-script reduce [scr] write to-file scr res2/data/script ] asis] div] [br [div/style/border:red+thin+solid [h2 Script Archive requests [p Use these requests to get archived versions of scripts (each time a script owner updates a script, we put the previous version in the archive. In some cases, the previous versions remain available for download). [h3 list-archive-versions [p REBOL.org usually only shows the latest version of each script. Previous versions may still be available. This request returns a list of all publicly available versions of a script. [li Parameters: script-name [li Response: archive-details [block] list] [h4 Example: [asis probe lds/send-server 'list-archive-versions [demo1.r] make object! [ status: [0 0 ""] data: make object! [ archive-versions: [ [7 15-Mar-2004 "Fixed bug in header"] [12 28-Apr-2004 "Version 2.0 -- supports IOS"] ] ] ] asis] [p In the above example, there are two publicly-available versions of the script: 7 and 12. The version number is an internal number to the Library. It will usually be different to the owners' version number in the script itself. [p The highest version number show will always be the current live version of the script. Lower numbered entries are back-versions of the script that the owner has left publicly available. [p To retrieve an archive version of a script use the request get-archive-version. [h3 get-archive-version [p Retrieve an archived version of a script (see list-archive-versions for more details) [li Parameters: script-name/version-number [string] Separate the two parts with a forward slash, eg "my-package/file1.txt" [li Response: script -- compressed file containing the script list] [h4 Examples: [p Get archive version 17 for script demo1.r: [asis probe res: lds/send-server 'get-archive-version ["demo1.r/17"] make object! [ status: [0 0 ""] data: make object! [ script: #{ 789CC551C14AC34010BDEF574C03524592565191F46015EB410445C54BE86193 snip ED800F8DA6768B8BCD39E0D9FE255DA877CE25EAB52D030000 } ] ] asis] [p demo1.r has a publicly available version 17, so it has been returned: [p Get archive version 14 for script demo1.r: [asis probe res: lds/send-server 'get-archive-version ["demo1.r/14"] make object! [ status: [301 "demo1.r" "not available"] data: none diagnostics: [41641 33710 0.11] ] asis] [p Version 14 of demo1.r is nor publicly available. If you need that exact version, contact the owner and ask them to make it available. div] [br [div/style/border:blue+thin+solid [h2 Update scripts requests [h3 contribute-script [p Use this request to either **add** a **new** script to the Library; or **update** an **existing** script that you own. [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with these words: **mode**, **note**, and **script**. Mode and script must always be present. Note is optional. [li mode -- can be "check" or "update". "check" means check that the script is okay, but do not actually add or update it. Use "check" to play around with this request without actually updating anything. "Update" means add (the new script) or update (the existing script) if all is well with it. [li note -- a note about why you are updating the script (eg "V2 adds extra video formats") [li script -- the script itself list] [h4 Example of the dialect: [p/class/notice note "changed error handling" mode "check" script {rebol [file: %zzz.r .....} [h4 Examples of use [asis scr: {rebol [] quit} response-object: lds/send-server/use-token 'contribute-script compose [mode "check" note "fix error handling" script (scr)] asis] [p This example does not send an acceptable script! This is what you'd get back: [asis Probe response-object make object! [ status: [210 30 "problems with script"] data: make object! [ validation: ["file" "We need a File: field in the REBOL header." "title" "We need a Title: field in the REBOL header." "date" {The Date: field in the REBOL header needs to be a valid REBOL date. (Not none)} "purpose" "We need a Purpose: string in the REBOL header."] ] ] asis] [h3 get-script-documentation [p Retrieve the documentation for a script, either as HTML or in its editable format [li Parameters: script name [string!] / format-wanted [string!] [list [li format-wanted is either **editable** or **html**. If omitted or incorrect, **editable** is assumed/ list] [li Response: documentation [compressed string!] list] [h4 Examples: [asis probe res: lds/send-server 'get-script-documentation ["lds- local.r/editable"] make object! [ status: [0 0 ""] data: make object! [ documentation: #{ 789CED7D6977DBD6D9E077FF8A1BF6742C69448AE04E2675476BDF74ECC68D9D E4EDE8B8E7402428210601160045AB99FCF77996BB622129937E9BCE8CCE492C 91C05D9EFBECDBFDC617B1BF08FED0C89369D36BBCFAE6CC7FF5CD43E7D5EBF0 2EF5D32771E5E7BE7817A48FE134C8BE39836F04FD7C330B1FC534F2B38C5E85 [snip] print decompress res/data/documentation [h2 Library Data Services [contents [asis Version: 0.0.5 12-Sep-2004 Sunanda [snip] asis] [h4 Note to script owners [p If you own a script, and check its download count on the **statistics page** of REBOL.org: LDS get-script downloads are counted as "Total LDS downloads". div] [br [div/style/border:green+thin+solid [h2 Script owner requests [p Use these requests to get information about a script that is only available to the script owner. [h3 List-my-scripts [p Returns the list of scripts that you own. Similar to list-scripts-owned-by, but you identify yourself by using a Library token. [li Parameters: none [li Needs token?: yes [li Response: list of scripts you own list] [h4 Example [p/class/notice response-object: lds/send-server/use-token 'list-my-scripts [] [h3 get-script-stats [p Returns owner statistics for the script -- only available if you own the script. [li Parameters: script-name [li Needs token?: yes [li Response: various counts and facts about the script list] [h4 Example [p/class/notice response-object: lds/send-server/use-token 'get-script-stats [lds-local.r] div] [br [div/style/border:yellow+thin+solid [h2 Package read requests [p Use these requests to query or retrieve files from packages. [p There is a also special LDS utility that makes working with packages easy: [p/class/notice do http://www.rebol.org/library/public/repack.r [h3 get-package-header [p Retrieve the header for a package -- i.e. the index to that package. [li Parameters: package-name [string!] [li Response: Object! -- containing details of all files in the package [list [li data/user-notes - text about the package [li data/package-file-list - one entry for each file or script in the package. List] list] [h4 data/package-file-list fields [li file-name -- name of the file [li install-folder -- a relative folder name suggesting where this file should be installed. [li last-updated - date and time stamp of when the file was last uploaded to the package [li cgi-type -- file type as reported by the browser that uploaded the file. Will be ""text/plain;library script" if the file is an existing script from the Library [li file-type -- one of three values [list [li file -- it's a file uploaded as part of the package [li script -- it's a script that is part of the Library, and has been included in this package [li package -- it's another package -- see "file-type: package" below for more notes on this list] [li notes -- any text the owner has entered about the file [li checksum -- a **checksum/secure** on the file contents. Use this to either check you get a valid copy of the file when downloading, or to bypass downloading if the local copy has the same checksum. [li file-size -- the size of the file after it is downloaded and decompressed [li compressed-size -- the size of the file to download (ie the compressed size) list] [h4 Possible errors. [p The package may not exist, or may not be available. See http://www.rebol.org/cgi-bin/cgiwrap/rebol/boiler.r?display=lds-package-dow nloader-help.html for a list of the package error messages [h4 Example -- header for package lds-demo1-package.r [asis probe res: lds/send-server 'get-package-header ["lds-demo1-package.r"] make object! [ status: [0 0 ""] data: make object! [ user-notes: {Run lds-demo1.r under REBOL/View and see if you can Spot The Developer!} package-file-list: [ make object! [ file-name: "image1.jpg" cgi-type: "image/pjpeg" install-folder: "images/" file-type: "file" version: 0.0.4 last-updated: 17-Apr-2004/16:17:19.39+1:00 notes: "" checksum: #{4001620992AE7B6974F159A6D957571CD1558E36} file-size: 17165 compressed-size: 12573 ] make object! [ file-name: "image2.jpg" cgi-type: "image/pjpeg" install-folder: "images/" file-type: "file" version: 0.1.0 notes: "" checksum: #{B76028C7C1D1DFFF2584788BEC82B8F7A8B55C07} file-size: 75276 compressed-size: 39052 ] etc -- one entry per file asis] [h4 file-type:package [p This means that the file is itself another package. That probably means that his package requires all the files from that package to be downloaded for a complete installation. [p The package header for the current package does not include all the files for the included package. If you are writing a package installer or downloader you may need to take into account file-type:package. If you do, issues include: [li the included package may be flagged as not available for download [li the included package may itself include other packages [li there may be loops in the inclusions. Perhaps Package1 includes Package2, and Package2 includes Package1. This should not be interpreted as an error -- it may simple be that both packages require the other one. List] [h3 get-package-file [p Retrieve one file from a package [li Parameters: package-name/file-name [string!] Separate the two parts with a forward slash, eg "my-package/file1.txt" [li Response: Object! -- file containing the compressed file list] [h4 Example -- file notes.txt package lds-demo1-package.r [asis probe res probe res: lds/send-server 'get-package-file ["lds-demo1-package.r/notes.txt"] make object! [ status: [0 0 ""] data: make object! [ file: #{ 789C7552D16ED3500C7D8F947F70DF3AD4A06D8C017B63A39B040C101DF0EC24 6E7AD5C48E1CA7617F8FEF6DD6371429B24F7C8E8FEDE4599EDDB5A1DA83096C 0CD5F26C89AD15D50B3898F46779F6BF67D38B81ED087EAE6FBF7F859A0ED44A snip 074DF93BCF8F8B9881F70EA41B9DFEB6237F9567171F8A7B2A8BCBF3F3AB3CFB 07C289D8E6C6020000 } ] ] asis] [h4 Notes [p The file as returned is compressed: [asis decompress res/data/file {^M ^M Click to Start^M (alt-click to stop)^M ^M ^M ^M ^M Spot the REBOL developer!^M asis] [p To save it, and lose all those ^M thingies in a text file, **always** save the file as **binary**: [asis write/binary %notes.txt decompress res/data/file print read %notes.txt Click to Start (alt-click to stop) Asis] [p Saving the file as **binary** is always the correct thing to do: the file may be a JPG or executable, or some other non-text format. div] [br [div/style/border:red+thin+solid [h2 Package update requests [h3 Overview before we start [p A package is a multi-file unit that makes up one contribution to the Library. [p From a user's perspective, it is three things: [list [li A script in the Library with a type header that includes the magic word 'package. This script will be just a dummy -- more like an index card that a real script. [li Zero or more uploaded files that make up the package [li Zero or more existing scripts from the Library that are included in the package. list] [p All the LDS requests for uploading or updating packages will need a Library token. [p Again, as with the contribute-script request, there is a mode parameter on every request. [li mode "check" will not perform the update -- thus making some testing easier [li mode "update" will be required for an update list] [h3 Transaction level support [p To create a full and usable package, several requests (perhaps many) have to be issued and succeed. If the server or the client fail part-way through, there will be an incomplete or unusable package left on public view. [p This is not so different from when a user is uploading files by hand to create a package -- their connection could fail at any point. I just mention in it case LDS clients want to get clever with some restart code. [p LDS itself will not be offering any sort of journaling or rollback. It sees and actions individual requests. [h4 Step 1: contribute-script [p Use contribute-script request to upload a new script. Include 'package in the Library header 'type field. [p After successfully contributing a new script, various automated mechanisms start telling the world the good news (email notices, RSS feed, ""what's new"" pages, etc) [p So some quick off-the-mark people may be looking at the new package before we've uploaded all the files. Nothing much we can do about that. It's part of the way packages were implemented as a bolt-on. [h4 Step 2: update-package-header [p Use this request to: [li optionally, add some header information to the package [li set the package as "unavailable" so people cannot download it while it is incomplete list] [h4 Step 3: upload-package-file [p Use this request for each of your files that are part of the package. [h4 Step 4: include-script-in-package [p Use this request for any existing Library scripts that are part of the package. [h4 Step 5: update-package-header again [p Use this again to set the package as "available". People can now download your new package. [h3 Steps involved in updating a package [p If you later need to change the package, use these steps: [h4 Step 1: update-package-header [p Set the package as "unavailable" to prevent people accidentally downloading an incomplete or inconsistent package [h4 Step 2: upload-package-file [p To add new files or update existing ones [h4 Step 3: remove-file-from-package [p To remove a file from the package [h4 Step 4 include-script-in-package [p To include additional Library scripts in the package [h4 Step 5 remove-script-from-package [p To remove a Library script from the package. [h4 Step 6: update-package-header [p Use this again to set the package as "available". People can now download your updated package. [h3 update-package-header [p Use this request to add or update the header details of a package [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with four "words": **mode**, **script-name** and **status** and **user-notes** [li mode -- can be "check" or "update". As per contribute-script [li script-name -- the name of the script. Must be present [li status -- sets the "available" status. Values are "private" or "public" [li user-notes -- optional notes about the package. list] [h4 Response [p A data object that normalises the dialect -- if you had any fields missing or with unacceptable values, you can see from the response what we assumed. [h4 Examples [p A full request looks something like: [asis lds/send-server/use-token 'update-package-header [script-name "example-package.r" mode "update" status "private" user-notes "Only works on MACs" ] asis] [p (As with all these requests, the order of the keywords in the dialect does not matter) [p These following examples stand in for a lot of detailed exposition about error checking and what we do with bad requests. [p The data section of the response is the internal, normalised dialect words -- so you can see how LDS-server has interpreted missing or bad data: [asis probe lds/send-server/use-token 'update-package-header [ script-name "example-package.r" mode "update" ] make object! [ status: [300 0 "unknown script"] data: make object! [ script-name: "example-package.r" mode: "update" status: none user-notes: none ] ] asis] [p Problem: no such script. Expect similar errors for: [li script is not a package (does not have a library header type: [... package ...]) [li script is not owned by you (ie not owned by owner of the token) list] [asis probe lds/send-server/use-token 'update-package-header [ script-name "example-package.r" user-notes "zzz" ] make object! [ status: [0 0 ""] data: make object! [ script-name: "example-package.r" mode: "check" status: none user-notes: "zzz" ] ] asis] [p Appears to have worked (got a 0 response), but the missing mode was taken as "check" -- so no changes made. [asis lds/send-server/use-token 'update-package-header [ script-name "example-package.r" mode "do it" user-notes "zzz" ] make object! [ status: [0 0 ""] data: make object! [ script-name: "example-package.r" mode: "check" status: none user-notes: "zzz" ] ] asis] [p Mode is bad (not "check" or "update") -- treated as its "safest" value, "check". Again, no update. [asis probe lds/send-server/use-token 'update-package-header [ script-name "example-package.r" mode "update" user-notes "zzz" ] make object! [ status: [0 0 ""] data: make object! [ script-name: "example-package.r" mode: "update" status: none user-notes: "zzz" ] ] asis] [p This one worked. It updated the user notes, but did not change the status (because none was specified). [asis lds/send-server/use-token 'update-package-header [ script-name "example-package.r" mode "update" status "confused" ] make object! [ status: [0 0 ""] data: make object! [ script-name: "example-package.r" mode: "update" status: "private" user-notes: none ] ] asis] [p This one worked, but may not have done what you expected. There was a status, but it was a bad value (neither "private" or "public") we normalised it to "private" that being the "safest" value. The user notes remain unchanged. [asis probe lds/send-server/use-token 'update-package-header [ script-name "example-package.r" mode "update" status "public" user-notes "" ] make object! [ status: [0 0 ""] data: make object! [ script-name: "example-package.r" mode: "update" status: "public" user-notes: "linux only" ] ] asis] [p Changes the status to "public" and sets the user notes to "" [h3 upload-package-file [p Use this to add or update details of a file in the package [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with these words: **mode**, **script-name**, **file-name**, **install-folder**, **user-notes**, **version**, **contents**, and **checksum**. Mode, script-name and file-name must always be present [li mode -- can be "check" or "update". As per contribute-script. [li script-name -- name of the script. Must be present [li file-name -- the name of the file. Must be present [li install-folder -- folder into which the downloaded file will be saved. Must be a **relative** path if present (do not start with "/". Must end with "/". "" is allowed to mean the default folder. [li contents -- the file itself as a compressed binary. Optional if you are changing the details (version, user-notes, install-folder) of a previously uploaded file [li checksum -- a checksum/secure of the pre-compressed file. Needed only if **contents** are present. Used to detect transmission errors in the upload. [li user-notes -- notes for the user about the file (eg "Not needed under Windows") [li version -- a version number for the file (eg 0.0.3) list] [h4 Examples [asis probe lds/send-server/use-token 'upload-package-file [script-name "example-package.r" mode "update" file-name "image-1.jpg" install-folder "images/" user-notes "Photo of Fluffy Bunny" version "0.0.5" contents #{...binary field...} checksum #checksum/secure of contents (to detect in-flight damage) ] asis] [p Uploads a new file (or completely replaces the details of an existing one) [asis lds/send-server/use-token 'upload-package-file [script-name "example-package.r" mode "update" file-name "image-1.jpg" install-folder "my/images/" user-notes "Better Photo of Fluffy Bunny" version "1.0.5" ] asis] [p Will change the install-folder, user-notes and version [asis lds/send-server/use-token 'upload-package-file [script-name "example-package.r" file-name "image-1.jpg" mode "update" user-notes "Even better Photo of Fluffy Bunny" ] asis] [p Will change just the user notes. [h4 What you get back [p Upload-package-file returns the normalised dialect, but the contents field is set to "[omitted]" -- no point sending back a 5meg file, or however large the file is. [h3 include-script-in-package [p Use this to include an existing Library script in the package. Note that you don't upload the script (after all, we already have it). You just tell us to make it part of the package. [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with these words: **mode**, **script-name**, **file-name**, **install-folder**, **library-script-name**. [li mode -- can be "check" or "update". As per contribute-script. [li script-name -- name of the script. Must be present [li file-name -- the name of the file. Must be present [li install-folder -- folder into which the downloaded library script will be saved. Must be a [li **relative** path if present (do not start with "/". Must end with "/". "" is allowed to mean the default folder. [li Library-script-name -- the name of the script to be made part of the package (eg "convert- base.r" or "values.r") list] [h4 Example [asis lds/send-server/use-token 'include-script-in-package [script-name "example-package.r" mode "update" library-script-name: "convert-base.r" install-folder "lib-scripts/" ] Asis] [h3 Remove-file-from-package [p Use this to remove a file you have uploaded to a package. [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with these words: **mode**, **script-name**, **file-name**, and **install-folder**. [li mode -- can be "check" or "update". As per contribute-script. [li script-name -- name of the script. Must be present [li file-name -- the name of the file. Must be present [li install-folder -- currently optional list] [h4 Example [asis lds/send-server/use-token 'remove-file-from-package [script-name "example-package.r" mode "update" install-folder: "" file-name "image-1.jpg" ] asis] [p image-1.jpg will not be a part of the package after this request is run. (Note: this does not mean it **was** a part of the package before; but, if it was, it isn't now) [h3 Remove-script-from-package [p Use this to remove a Library script from the package. [li Parameters: simple dialect -- see below [li Needs token?: Yes [li Response: complex object -- see below list] [h4 Parameters [p Are a dialect with these words: **mode**, **script-name**, **file-name**, **install-folder**, **library-script-name**. [li mode -- can be "check" or "update". As per contribute-script. [li script-name -- name of the script. Must be present [li library-script-name -- the name of the Library script to be removed [li install-folder -- installation folder to which the script was to be installed list] [h4 Example [asis lds/send-server/use-token 'remove-script-from-package [script-name "example-package.r" mode "update" install-folder: "" Library-script-name "convert-base.r" ] asis] [p /convert-base.r will not be a part of the package after this request is run. (Note: this does not mean it **was** a part of the package before; but, if it was, it isn't now) div] [br [div/style/border:green+thin+solid [h2 Other requests [h3 rss-get-feed-data [p Retrieves the raw data used to generate the Library's RSS feed. [p You can subscribe to the Library's RSS feed by visiting [link http://www.rebol.org/cgi-bin/cgiwrap/rebol/rss-get-feed.r "get RSS feed." [p Alternatively, you can used this LDS request to retrieve the same data as a REBOL object. In addition, there are some extra fields not supplied to the RSS readers. [li Parameters: none [li Response:response object -- see below List] [h4 response object [p has these fields: [li **generation-info** -- an object with useful status details [li **script-library** -- a block with an object for each script included in the feed [li **mailing-list-archive** -- a block with an object for each mailing list thread included in the feed [li **news** -- a block with details of each ""news"" headline list] [h4 response object/generation-info [p Has these useful fields [li **rss-test-mode** -- should always be false. [li **timestamp** -- precise timestamp for when the RSS feed data was last generated [li **supply?** -- will be **generated** if your request has triggered the Library into generating a fresh set of RSS feed data; or **cached** if you are being supplied some slightly older data. Note that **cached** does not usually mean **stale**. Even cached data is likely to be very close to real-time accurate. [li **data-range** -- a block with two dates; showing the start and end date of the range for the RSS feed. [li **timings** -- for testing list] [h4 response object/script-library [p Is a block of objects, one per script included in the RSS feed data. [li **script-name** -- the name of the script [li **link** -- the URL to view it [li **update-type** -- **updated** or **new** [li **entry-date** -- when the script was added or last updated [li **title** -- from the script's **title** header [li **purpose** -- from the script's **purpose** header [li **version** -- from the script's **version** header [li **owners** -- a block with zero or more Library member's names; these are the members who own (and can thus update) the script [li **change-note** -- a note added when the owner last updated the script to explain why it is changing. list] [h4 response object/mailing-list-archive [p Is a block of objects, one per included in the RSS feed data. [li ** msgid** -- the mailing list message id of the first message in the thread [li **subject** -- the subject line of the first message in the thread (note that it is possible for later messages in the same thread to have different subject lines). [li **new-messages** -- a block with two data items per message: [list [li **message date** -- the date the message was entered into the ML archive [li **message id** -- the message id of the message list] There will be an entry (date and message id) in the block for each message in the thread that is included in the RSS feed data: [list [li if this block includes the **msgid** of the first message in the thread, then this is a new thread; [li if it does not, then this is an old thread that has one or more new messages in it. list] list] [h4 response object/news [p Is a block of objects, one per news item included in the RSS feed data. News is the little snippets you can find on the top right of the REBOL.org home page. [li **title** -- headline [li **link** -- URL for further information [li **date** -- date news item added [li **content** -- text of the information paragraph. list] [h4 Example [asis probe lds/send-server 'rss-get-feed-data [] Asis] [line div] [br [div/style/border:yellow+thin+solid [h2 Token requests [p Use these requests to work with your Library tokens. [h3 token-test [p Test if your Library token works: [li Parameters: any text [li Token required: yes [li Response: Object! -- your text back list] [p If the token is valid, you get your text back. If not, you get an error message about the token [h4 Example: [p/class/notice response-object: lds/send-server/use-token 'token-test ["any text"] [h3 token-cancel [p Cancels your current token. It will never work again. [li Parameters: none [li Token required: yes [li Response: Object! -- status list] [h4 Example: [p/class/notice response-object: lds/send-server/use-token 'token-cancel [] div] [br [div/style/border:red+thin+solid [h2 Random points and answers to NAQs (never-asked questions) [h3 Why not use LNS (Lightweight Network Services)? [p LDS predates LNS by a year, so LNS simply wasn't a possibility. [p It would be good to add an LNS interface to the Library. If any one wants to volunteer to help with that, please drop us a **feedback** message [h3 Validation and verification [p All validation and verification of requests is done on REBOL.org. Lds-local does no parameter checking -- it simply passes the parameters you supply to REBOL.org. [h3 Sorting [p The lists you get back from LDS are not usually not sorted. Any sequencing is purely accidental, and should not be relied on. LDS provides the data, it is your choice what order to handle or present it. [p One exception is the ''search-scripts request. The scripts-list it returns is sorted according to the relevance of the results: best fit first. [h3 Caching [p Each time you call lds/send-server, it talks to the REBOL.org server. There is a case for caching results as many things do not change that often. It's on the upgrade list. [h3 XML [p I've been thinking of adding an XML refinement: [p/class/notice lds/send-server/xml 'help none [p So what you get back is an XML page, not a REBOL object. Easy to do, but no point, unless anyone needs it. div] [p/class/notice+ca end