View · Search · Index


Filtered by category OpenACS Projects, 1 - 10 of 44 Postings (all, summary)


Created by Dave Bauer, last modified by Gustaf Neumann 24 Apr 2019, at 12:59 PM

Release Status

See openacs-release-status

Development is taking place in the oacs-5-10 branch.

OpenACS Version 5.10.0 Agenda/wish list

  • postponed for later releases:
    • implement subsite-singleton (in addition to the classical singleton)
    • say farewell to CVS
  • Functional improvements
    • additional page_contract filter: oneof(red|green|blue)
    • add text/markdown to the accepted text formats or rich-text widget
    • new API call  category::get obtain as well category description for a category_id and locale
    • visualize code dependencies and test-coverage in API browser
    • new feature to warn site administrators about expiring certificates
    • dynamic reloading reform:
      • When reloading  apm packages, watched files, etc. the NaviServer blueprint is now updated correctly. This solves the long-standing problem that changes for scheduled procedures required a restart of the server. Furthermore the old-style reloading was based on a ever-growing list of reload operations each time a new reload was requested, causing slow-downs in long running server instances, especially, when new threads are started.
      • Now changes are applied to all NaviServer threads, including threads for
        schedules procedures, ns_jobs and the like. Note that the current job has to be finished before the changes can be applied.
      • For the transition, it is possible to switch between the classical reloading style and blueprint reloading by changing a variable in acs-tcl/tcl/apm-procs.tcl
    • new packages:
      • cookie-consent: alerting users about the use of cookies on a website
      • boomerang: performance of your website from your end user’s point of view
    • Forums reform:
      • remove hard-coded dependency with registered_users group when checking forum permissions
      • don't rely so heavily on acs_permissions to model forum configuration, as this can have unexpected consequences in convoluted multi-group/multi-subsite scenarios. Prefer simpler table attributes instead
    • Registry for .js and .css libraries: allow besides classical URLs symbolic names for loading external resources (e.g. jquery), this makes it easier to upgrade  libraries in multiple packages (without running into problems with duplicate versions) and supports  switching between CDN and local pathsURN.
      The existing implementation is based on URNs and extends the existing template-head API to
      support registration for URNs. A URN provides an abstraction and a single place for e.g updating references to external resources when switching between a CDN and a locally stored resource, or when a resource should be updated. Instead of adding e.g. a CDN URL via template::head::add_script, one can add an URN and control its content from a single place. Use common namespaces for OpenACS such as urn:ad:css:* and urn:ad:js:*.
      • Register URNs:

        Example provider (e.g. in some theme):
           template::register_urn \ 
               -urn urn:ad:js:jquery \ 
               -resource /resources/xowiki/jquery/jquery.min.js
      • The registered URN can be used like classical URL after registration.
        Example consumer:

           template::head::add_javascript -src urn:ad:js:jquery
      • Declare composite files: Provide an interface to define that  a .js file or a .css file contains multiple other .js/.css files in order to reduce the number of requests.
           template::head::includes -container urn:js::style.js -parts {urn:ad:js:jquery ...}
  • non-functional changes
    • Improved regression testing
      • Goal is that all packages in oacs-5-10 pass regression test
      • Include web testing in standard regression testing
    • Improved scalability:
      • Data bloat hygiene:
        • rethink package parameter and portlet parameter data models
        • parameters: include "subsite-parameters" in parameter resolution (package->subsite->global)
      • provide lock-free implementation of ad_page_contract_filters and ad_page_contract_filter_rules. This change improves parallel processing of requests and is primarily interesting for sites with a few mio page views per days. These locks were among the most frequent nsv locks

      • Reduced locks on util_memoize_cache my more invariants values into per-thread caching (acs_lookup_magic_object, ad_acs_version, .... ) and by avoiding specialized calls, which can be realized by already optimized ones ("apm_package_installed_p_not_cached ref-timezones" was most frequently used util_memoize_cache entry). These changes are necessary to avoid full still-stand on the unfortunate long-time locks on util_memoize_cache stemming from permission and user management with wild-card flush operations, which require to iterate over all cache entries (which might be a server hundred thousands)

      • Added new interface for cache partitioning to reduce lock latencies on high load websites

    • Code smell reduction: fix typos, white-space etc.
    • Security improvements:
      • strengthen page contracts
      • CSP fine tuning
    • Better exception handling based on Tcl 8.6 exception handlers ("try" and "throw", also available in Tcl 8.5)
      • a new "ad_try" implementation based on Tcl's "try" replaces now the old "ad_try", "with_catch" and "with_finally", which are marked as deprecated
      • the new "ad_try" is in essence Tcl's "try" but with predefined handling of "ad_script_abort" and should be also used instead of "catch", when the OpenACS API is used (which might use script aborts)
      • all core packages use the new "ad_try" instead of the deprecated versions
    • Connection close reform:
      • NaviServer/AOLserver continue after connection closing commands to execute a script. This is in many situation not desired, especially, when for the page as well a .adp file exists, which will try to deliver this on the already closed connection. This can lead to errors in the error.log file, which are sometimes hard to analyze
      • therefore, developers should use in most such cases cases "ad_script_abort"
      • connection closing commands are e.g. ad_returnredirect, ad_redirect_for_registration, cr_write_content, ad_page_contract_handle_datasource_error, ad_return_string_as_file, ad_return_complaint,  ad_return_error,
        ad_return_forbidden, ad_return_warning, ad_return_exception_page, ns_returnredirect, ns_return, ns_returnerror
      • The new version has made on most occasions explicit, when the script should abort.
    • SQL cleanup:
      • cleanup of obsolete non-portable SQL constructs in a way Oracle and PostgreSQL code base divergency is reduced:
        • "nvl" -> "coalesce"
        • "sysdate" / "now()" -> standard "current_date" or "current_timestamp"
        • use standard-compliant "dual" table where appropriate (required by Oracle, supported by Postgres)
        • use non-dialectal cast idioms when appropriate
        • ... (reference Oracle version will be 11.2 as is oldest version officially supported by Oracle)
      • reduce superfluous .xql queries
        • acs-subsite: delete 21 files with un-referenced .xql queries
        • acs-tcl: delete 4 files
        • news: 3 files
        • file-storage: 1 file
        • dotlrn: 9 files
    • Deprecated commands:
      • move deprecated code into separate files
      • make loading of deprecated code optional (can be controlled via parameter  "WithDeprecatedCode" in section "ns_section ns/server/${server}/acs" of the config file. By default, deprecated procs are still loaded
      • When deprecated code is not loaded, the blueprint of the interpreter is smaller. The following number of lines of code can be omitted when loading without the deprecated procs:
        • acs-tcl: 3178
        • acs-templating: 450
        • xotcl-core http-client-procs: 830
        • acs-content-repository: 1717 (including .xql files)
    • Improves handling of server implementation-specific code
      • provide *-procs-aolserver.tcl and *-procs-naviserver.tcl similar to *.postgresql.xql and *.oracle.xql where appropriate
  • require Tcl 8.6, XOTcl 2.1, PostgreSQL 9.4 (PostgreSQL 9.3 EOL: November 2018), tdom 0.9
  • Make xotcl-core a first-class citizen of the OpenACS core! (wished by Michael Aram; would probably require a successful TIP?)

OpenACS Version 5.9.1 Agenda

Refactoring of rich-text editor integration

  • Driving force: Debian packaging (e.g. js minified code is not allowed)
  • Moved out code from acs-templating, provided interfaces to add many different rich-text editors as separate packages
  • New OpenACS packages:
    • richtext-xinha
    • richtext-tinymce
    • richtext-ckeditor4 (has ability to choose between CDN and local installation via web interface)

Improving admin interface

  • New theme manager:
    • Goals:
      • Make it easier to keep track of themes with local modifications
      • Make it easier to create local modification a new themes and to update these
      • Show differences between default theme parameter (in DB) and actual settings (in subsite parameters)
      • Allow to delete unused themes
      • Give site admin hints, which theme is used at which subsite
      • Ease theme switching
    • Added a subsite::theme_changed callback to be able to handle theme changes in custom themes (was also necessary for proper integration with DotLRN theming)
    • Added support for these features under subsite admin (/admin/)
    • Improved support for themed templates via [template::themed_template]


  • Improved (broken) interface to define/manage groups over web interface
  • Allow to send as well mail, when membership was rejected
  • New functions [membership_rel::get_user_id], [membership_rel::get] and [membership_rel::get_group_id] to avoid code duplication
  • Added support to let user include %forgotten_password_url% in self-registration emails (e.g. in message key acs-subsite.email_body_Registration_password)


  • Improved subsite/www/members
    • Make it possible to manage members of arbitrary groups
    • Improved performance for large groups
    • Improved configurability: when ShowMembersListTo is set to "3", show list to members only, when this is not the whole subsite


  • Improved user interface for /admin/applications for large number of applications
  • Various fixes for sitewide-admin pages (under /acs-admin)
  • Update blueprint in "install from repository" (currently just working in NaviServer)


  • Further cleanup of .xql files (like what as done for acs-subsite in OpenACS 5.9.0):
    • 36 files deleted
    • Removed more than 100 obsolete named queries
    • Stripped misleading SQL statements


  • Marked redundant / uncalled SQL functions as deprecated
  • Replaced usages of obsolete view "all_object_party_privilege_map" by "acs_object_party_privilege_map"
  • Removed type discrepancy introduced in 2002:
    • acs_object_types.object_type has type varchar(1000), while
    • acs_object_types.supertype has type varchar(100)
    • ... several more data types are involved, using acs_object_types.object_type as foreign key


  • Simplified core SQL functions by using defaults:
    • Number of functions reduced by a factor of 2 compared to OpenACS 5.9.0 (while providing compatibility for clients using old versions),
    • Reduced code redundancy
    • Affected functions:
      • Reduced content_item__new from 12 versions to 6,
      • Reduce content_revision__new from 7 to 4
      • Similar in image__new, image__new_revision, content_item__copy, content_item__get_title, content_item__move
    • PostgreSQL 9.5 supports named parameter in the same syntax as in Oracle. Further reduction of variants will be possible, once OpenACS requires at least PostgreSQL 9.5


  • Reduced usage of deprecated versions of SQL functions (mostly content repository calls)
  • Reduced generation of dead tuples by combining multiple DML statements to one (reduces costs of checkpoint cleanups in PostgreSQL)


  • Permission queries:
    • Improved performance
    • Support PACKAGE.FUNCTION notation for PostgreSQL to allow calls permission queries exactly the same way as in Oracle (e.g. "acs_permission.permission_p()"). This helps to reduce the number of PostgreSQL specific .xql files.
  • Modernize SQL:
    • Use real Boolean types instead of character(1)
      (done for new-portal, forums, faq, attachments, categories, dotlrn, dotlrn-forums, evaluation)
    • Use real enumeration types rather than check constraints (done for storage_type text/file/lob)

CR hygienics (reduce cr bloat)

  • Provided means to avoid insert/update/delete operations in the search queue:

    OpenACS adds for every new revision often multiple entries to the search_queue, without providing any means to prevent this. This requires for busy sites very short intervals between queue sweeps (otherwise too many entries pile up). Another consequence is that this behavior keeps the PostgreSQL auto-vacuum daemons permanently active. Many of these operations are useless in cases where the content repository is used for content that should not be provided via search. The changed behavior should honors a publish-date set to the future, since it will not add any content with future publish dates to the search-queue.


  • Reduced number of insert cr_child_rels operations, just when needed:

    cr_child_rels provide only little benefit (allow to use roles in a child-rel), but the common operation is a well available in cr_items via the parent_id. cr_child_rels do not help for recursive queries either. One option would be to add an additional argument for content_item__new to omit child-rel creation (default is old behavior) and adapt the other cases.

Security improvements

  • Added support against CSRF (cross site request forgery)
    • OpenACS maintains a per-request CSRF token that ensures that form replies are coming just from sites that received the form
    • CSRF support is optional for packages where CSRF is less dangerous, and such requests are wanted (e.g. search and api-browser)
  • Added Support for W3C "Upgrade-Insecure-Headers" (see
    For standard compliant upgrade for requests from HTTP to HTTPS

  • Added support for W3C "Subresource Integrity" (SRI; see

  • Added support for W3C "Content Security Policy" (CSP; see

    • Removed "javascript:*" links (all such urls are removed from the 90 packages in oacs-5-9, excluding js libraries (ajaxhelper) and richtext code)
    • Removed "onclick", "onfocus", "onblur", "onchange" handlers from all .adp and .tcl files in the 90 packages in oacs-5-9 (excluding js libraries (ajaxhelper) and richtext code)
    • Added optional nonces to all <script> elements with literal JavaScript content


  • Removed "generic downloader", which allowed to download arbitrary content items, when item_id was known (bug-fix)
  • Improved protection against XSS and SQL-injection (strengthen page contracts, add validators, added page_contract_filter "localurl", improve HTML escaping, and URI encoding)
  • Fixed for potential traversal attack (acs-api-documentation-procs)

Improvements for "host-node mapped" subsites

  • Fixed links from host-node mapped subsite pages to swa-functions (must be always on main subsite)
  • Made "util_current_directory" aware of host-node-mapped subsites
  • Added ability to pass "-cookie_domain" to make it possible to use the same cookie for different domains
  • Fixed result of affected commands "util_current_location", "ad_return_url", "ad_get_login_url" and "ad_get_logout_url" for HTTP and HTTPS, when UseHostnameDomainforReg is 0 or 1.
  • Improved UI for host-node maps when a large number of site nodes exists

Reform of acs-rels

  • Made acs-rels configurable to give the developer the option to specify, whether these are composable or not (default fully backward compatible). This is required to control transitivity in rel-segments
  • The code changes are based on a patch provided by Michael Steigman.
    For details, see:

Improved status code handlers for AJAX scenarios

  • Don't report data source errors with status code 200 (use 422 instead)
  • Let "permission::require_permission" return forbidden (403) in AJAX calls (determined via [ad_conn ajaxp])

Improved Internationalization

  • Extended language catalogs for
    • Russian (thanks to v v)
    • Italian (thanks to Antonio Pisano)
    • Spanish (thanks to Hector Romojaro)
    • German (thanks to Markus Moser)


  • Added (missing) message keys
  • Improved wording of entries
  • Added message keys for member_state changes, provide API via group::get_member_state_pretty

Improved online documentation (/doc)

  • Fixed many broken links
  • Removed fully obsolete sections
  • Improved markup (modernize HTML)
  • Updated various sections

Misc code improvements:

  • 18 issues from the OpenACS-bug-tracker fixed
  • Made code more robust against invalid/incorrect input (page_contracts, validators, values obtained from header fields such as Accept-Language)
  • Fixed quoting of message keys on many places
  • Improved exception handling (often, a "catch" swallows to much, e.g. script_aborts), introducing "ad_exception".
  • Generalized handling of leading zeros:

    • Fixed cases where leading zeros could lead to unwanted octal interpretations
    • Switch to use of " util::trim_leading_zeros" instead of "template::util::leadingTrim", "dt_trim_leading_zeros" and "template::util::leadingTrim", marked the latter as deprecated
  • URL encoding

    • "ad_urlencode_folder_path": new function to perform an urlencode operation on the segments of the provided folder path
    • "export_vars": encode path always correctly, except -no_base_encode is specified
    • Fixed encoding of the URL path in "ad_returnredirect"
  • Improvements for "ad_conn":

    • Added [ad_conn behind_proxy_p] to check, whether the request is coming from behind a proxy server
    • Added [ad_conn behind_secure_proxy_p] to check, whether the request is coming from behind a secure proxy server
    • Added [ad_conn ajax_p] to check, whether the request is an AJAX requests (assumption: AJAX request sets header-field Requested-With: XMLHttpRequest")
    • Added [ad_conn vhost_url] to obtain the url of host-node-mapped subsites


  • Added various missing upgrade scripts (missing since many years) of changes that were implemented for new installs to reduce differences between "new"-and "old" (upgraded) installations
  • Templating

    • Get rid of various pesky "MISSING FORMWIDGET: ...formbutton:ok" messages
    • Improved support for javascript event handlers in template::head
    • New functions "template::add_event_listener" and "template::add_confirm_handler"
    • Fix handling, when "page_size_variable_p" is set (was broken since ages)
  • Improved location and URL handling:

    • Refactored and commented "util_current_location" to address security issues, handle IPv6 addresses, IP literal notation, multiple drivers, "
    • Improved "security::get_secure_location" (align with documentation)


    • New functions:
      • "util::configured_location"
      • "util::join_location", "util::split_location"
      for working on HTTP locations to reduce scattered regexps handling URL components
    • Improved IPv6 support
    • Use native "ns_parseurl" when available, provide backward compatible version for AOLserver
  • MIME types:

    • Added more Open XML formats for MS-Office to allowed content types
    • Modernized entries to IANA recommendations
    • New function "cr_check_mime_type" centralizing the retrieval of the mime_type from uploaded content
  • Finalized cleanup of permissions (started in OpenACS 5.9.0):

    • Get rid of "acs_object_context_index " (and therefore on "acs_object_party_privilege_map " as well) on PostgreSQL.
      • huge table,
      • expensive maintenance, used only in a few places,
  • Misc new functions:

    • "lang::util::message_key_regexp": factor out scattered regexp for detecting message keys
    • "ns_md5" and "ns_parseurl": improve compatibility between AOLserver and NaviServer
    • "ad_dom_sanitize_html": allow to specify different sets of tags, attributes and protocols and "ad_dom_fix_html", which is a light weight tidy variant.


  • Improved HTML rendering (acs-api-browser), provide width and height to speed up rendering
  • Improved ADP files (e.g. missing doc(title))
  • Added usage of "ad_include_contract" on more occasions
  • Modernize Tcl and HTML coding
  • Reduced dependency on external programs (use Tcl functions instead)
  • Improved robustness of "file delete" operations all over the code
  • Improved documentation, fix demo pages
  • Aligned usages of log notification levels (distinction between "error", "warning" and "notice") with coding-standards


  • Cleaned up deprecated calls:
    • Removed usage of deprecated API functions (e.g. "cc_lookup_email_user", "cc_email_from_party", "util_unlist", ...)
    • Moved more deprecated procs to acs-outdated
    • Marked remaining (and unused) "cc_*" functions as well as deprecated.


  • Improved Oracle and windows support
  • Fixed common spelling errors and standardize spelling of product names all over the code (comments, documentation, ...)
  • Many more small bug fixes

Version numbers:

  • require PG 9.2 (End Of Life of PostgreSQL 9.0 was Oct 2015)
  • require XOTcl 2.0 (presented at the Tcl conference in 2011).




  • New Package Parameters

    • acs-kernel:

      • MaxUrlLength: remove hard-coded constant in request processor for max accepted url paths
      • SecureSessionCookie: Let site admin determine, whether or not to use secured session cookies (useful, when not all requests are over HTTPS)
      • CSPEnabledP: activate/deactivate CSP
    • acs-kernel (recommended to be set via config file in section "ns/server/${server}/>acs"

      • NsShutdownWithNonZeroExitCode: tell NaviServer to return with a non-zero return code to cause restart (important under windows)
      • LogIncludeUserId: include user_id in access log
    • acs-api-browser:

      • ValidateCSRFP: make checking of CSRF optional (default 1)
    • acs-content-repository:

      • AllowMimeTypeCreationP: Decides whether we allow unknown mime types to be automatically registered (default: 0}
    • news-portlet:

      • display_item_lead_p: Should we display news leads in the portlet? (default 0)
    • search:

      • ValidateCSRFP: make checking of CSRF optional (default 1)
    • xotcl-request-monitor:

      • do_track_activity: turn activity monitoring on or off (default 0)
  • New OpenACS packages:

    • richtext-xinha
    • richtext-tinymce
    • richtext-ckeditor4 (has ability to choose between CDN and local installation via GUI)
    • openacs-bootstrap3-theme (as used on
    • dotlrn-bootstrap3-theme
  • xotcl-core:

    • Improved XOTcl 2.0 and NX support (e.g. api-browser)
    • Added "-debug", "-deprecated" to ad_* defined methods (such as e.g. "ad_instproc")
    • Make use of explicit "create" statements when creating XOTcl/NX objects (makes it easier to grab intentions and to detect typos)
    • Added parameter to "get_instance_from_db" to specify, whether the loaded objects should be initialized
    • Added support for PostgreSQL prepared statements of SQL interface in ::xo::dc (nsdb driver)
  • xowiki:

    • Named all web-callable methods www-NAME (to make it clear, what is called, what has to be checked especially carefully)
    • Moved templates from www into xowiki/resources to avoid naming conflicts
    • Improved ckeditor support
    • Added usage of prepared statements for common queries
    • Improved error handling
    • Better value checking for query parameter, error reporting via ad_return_complaint
    • Added option "-path_encode" to methods "pretty_link" and "folder_path" to allow to control, whether the result should be encoded or not (default true)


    • Form fields:
      • Improved repeatable form fields (esp. composite cases), don't require preallocation (can be costly in composite cases)
      • Added signing of form-fields
      • Added HTML5 attributes such as "multiple" (for "file") or "autocomplete"
      • Fixed generation of "orderby" attribute based on form-field names
      • richtext: allow to specify "extraAllowedContent" via options
      • Improved layout of horizontal check boxes


    • Menu bar:
      • Added dropzone (requires bootstrap): drag and drop file upload
      • Added mode toggle (requires bootstrap)
      • Extended default policies for handling e.g. dropzone (file-upload method)
      • Distinguish between "startpage" (menu.Package.Startpage) and "table of contents" (menu.Package.Toc)


    • Notifications:
      • Added support for better tailorable notifications: introduced method "notification_render" (similar to "search_render")
      • Added support for tailorable subject lines (method "notification_subject")


    • Improved bootstrap support, use "bootstrap" as PreferredCSSToolkit
    • Switched to ckeditor4 as PreferredRichtextEditor
    • Improved handling of script-abort from within the payload of ::xowiki::Object payloads
    • Added parameter to "get_all_children" to specify, whether the child objects should be initialized
  • xowf:

    • Added property "payload" to "WorkflowConstruct" in order to simplify customized workflow "allocate" actions
    • Internationalized more menu buttons
  • xotcl-request-monitor

    • Added class "BanUser" (use. e.g. ip address to disallow requests from a user via request monitor)
    • Added support for optional user tracking in database
    • Added support for monitoring response-time for certain urls via munin
    • Increased usage of XOTcl 2.0 variable resolver (potentially speed improvement 4x)
    • Performed some refactoring of response-time handling to allow site-admin to make e.g. use of NaviServer's dynamic connection pool management (not included in CVS)
    • Added support for partial times in long-calls.tcl to ease interpretation of unexpected slow calls
    • last100.tcl: Don't report hrefs to URLs, except to SWAs
  • chat:

    • Introduced new options to set chat rooms so login and/or logout message are not issued every time a user enters/exits a chat-room (important for chats with huge number of participants)
    • Parameterized viewing of chat-logs
    • Fixed cases of over-/under-quoting
    • Fixed JavaScript for IE, where innerHTML can cause problems
  • file-storage:

    • Don't show action keys, when user has no permissions
    • Added support for copying of same-named files into a folder (adding suffix)
    • Fixed old bugs in connection with "views" package

OpenACS Version 5.9.0 Agenda

  • Slimming pg SQL core:
    • Part 1: improve performance of object deletion
      • remove manual delete operations from acs_object__delete()
    • Part 2: content-repository - manual referential integrity management
      • handle referential integrity via pg's integrity constraints rather by functions cr_revision_del_ri_tr, cr_revision_ins_ri_tr, cr_revision_up_ri_tr, cr_revision_del_rev_ri_tr, and cr_revision_del_rev_ri_tr
      • fix broken/missing upgrade scripts from earlier updates
    • Part 3: content-repository - manual deletions and nulling
      • Removed manual nulling of live_revision and latest_revision
      • Removed manual deletion of old_revision and new_revision in cr_item_publish_audit
      • Removed manual deletion of item_id in cr_item_publish_audit, cr_release_periods, cr_item_template_map, and cr_item_keyword_map
      • Removed manual deletion of direct permissions
      • Added missing index for child_id to cr_child_rels.
    • Part 4: get rid of tree_sortkey in acs-objects
      • Check/fix dependencies in oacs-5-8 packages
      • Get rid of broken/uncalled functions using the column
      • Check/fix dependencies in other packages
      • Remove tree_sortkey and max_child_sortkey
  • Web interface:
    • Improve client performance
      • moving core.js from head to body
      • provide kernel parameter to control expiration date for /resources/
    • Protect against more XSS attacks
    • Improved HTML validity (see oacs-5-9-html-validity for the checklist)
    • Add lightweight support for ckeditor4 for templating::richtext widget (configurable via package parameter "RichTextEditor" of acs-templating. ckeditor4 supports mobile devices (such as iPad, ...).
    • New kernel parameter ResourcesExpireInterval to control expiration dates of resources
  • Templating:
    • Improve theme-ability
      • Move more information into theme packages in order to create responsive designs
      • Reduce hard-coding of paths, HTML etc.
    • Dimensional slider reform (ad_dimensional):
      • Remove hard-coded table layout from dimensional slider
      • Add backwards compatible templates
      • Move hard-coded styles into theme styling
      • Remove obsolete comments from ad_dimensional
    • Complete template variable controls (adding noi18n, addressing bug #2692):
      • @foo@: perform html quoting and internationalization
      • @foo;noquote@: perform internationalization
      • @foo;noi18n@: perform html quoting
      • @foo;literal@: perform neither html quoting nor internationalization
    • Improved Russian nationalization
    • Support of expiration dates and passwords for signed variables
  • Documentation:
    • Use ACS templating for the (static) OpenACS documentation to provide a more consistent layout and user experience.
    • Make pretty-naming of acs-core packages more consistent.
  • Misc improvements:
    • Mark unused functions of acs-tcl/tcl/table-display-procs.tcl as deprecated
    • Reduce number of muxtex locks by pre-request and per-thread caching
    • Improved development und debugging aids:
      • use "ad_log error|warning  .... " instead of "ns_log" to include information of request and callstack in error.log
      • ability to display ns_log entries caused by a request in ds-footer
      • ability to save delivered web pages in file-system for testing HTML validity (especially for admin pages, which are unaccessible for external validity testers)
    • More bug fixes
  • Version numbers:
    * require PG 9.0 (End Of Life of PostgreSQL 8.4 was July 2014)
    * require XOTcl 2.0 (presented at the Tcl conference in 2011).

OpenACS Version 5.8 Agenda

  • PostgreSQL 9.2+:
    • Get rid of nonstandard backslash escapes in function definitions
    • Change quote syntax in sql files (single quotes around the functions) to recommended PostgreSQL quoting using (recommended since pg8.0, jan 2005). li>Drop aliases in favor of named function arguments (recommended since pg8.0)
    • Fix wrong function_args, add missing function_args, align default semantics with the defaults in pg (providing "null" as default means the argument is optional)
    • Make OpenACS loadable without any tweaks in the pg config files
  • Use recursive queries for e.g. permission lookup to avoid performance problems in pg 8.4 and newer)
  • ADP: Use byte-compiled function wherever possible in compiled adp-code, support "@var;literal@" when neither quotes nor localization is needed in compiled adp-code
  • Improve support of NaviServer
  • Switch to Tcl 8.5 (TIP #143)
  • Improve scalability: Reduce mutex-stress on util-memoize cache and for cache maintenance in general
  • Code cleanup:
    • Get rid of calls to deprecated code (e.g. ad_tables, ad_parameter, ... in acs-core and main packages)
    • Improve awareness of usage of deprecated code (complain to error.log)
    • Use Tcl 8.5 idioms
    • cleanup of various http-client approaches and introduce a common implementation util::http::get and util::http::post; get rid of other usages, mark these as deprecated
    • page-contracts: Perform checking of all ids in acs-core and main packages to improve error messages and to improve security
  • OpenACS 5.8.1 should be released with main packages

OpenACS Version 5.7 Agenda

  • Support for object management in core 
  • Postgresql 9.0
  • TinyMCE update (fix for random JS injection issue, affecting Safari)
  • Fix for "remember me" issue
  • WCAG2-AA

OpenACS Version 5.6 Agenda

  • global parameters
  • package "embeds" 
  • fix search by package_id
  • core works on Postgresql 8.4

OpenACS Version 5.5 Agenda

  • DONE: Postgresql 8.3 support: especially regarding tsearch2
  • DONE: acs-authentication:
    • fix upgrade, add conditional logic into site wide tcl library so that you can login to perform the rest of the upgrade
  • DONE: tinymce:
    • upgrade to 3.1.1 + language packs
    • HTML Strict cleanup
    • create appropriate parameters for its config in acs-templating
  • acs-mail-lite:
    • DONE: cleanup duplicated procs (bounce)
    • review the parsing of bouncing messages (case user_id 0)
    • DONE: rollout support
  • Documentation improvements as discussed at the Guatemala conference:
    • Make current source for static files included in the release and provide ease means to achieve this for the release manager
      • DONE (CVS HEAD): Provide in XoWiki an alternative table of contents by nested UL/LI (without JavaScript) for static output
      • DONE (CVS HEAD): Provide in XoWiki a prototype page similar to "book" without edit-buttons etc., using the new table of contents
    • Update where necessary (incomplete list):
      • DONE: Fix the page ordering for the higher chapters (the original document  had no 3rd. level numbering)
      • update pages in /test-doc which are more recent in openacs/xowiki
      • bump version numbers of OpenACS, where appropriate (some places talk about openacs-5-0, others about openacs-5-1, oacs-5-2-3rc1 or 5-3) 
      • some version numbers of the required components are quite a mess. e.g. some parts say that Postgres 7.3 is required,  some examples talks about postgres 7.4.7 and 8.2.4 in the same listing.
      • also the dotlrn version numbers are old dotrln-2.0
      • Tcl version numbers should be 8.4.19
      • The install section for XOTcl is missing in II.3.4
      • remove ChangeLog from documentation
      • find some other prominent place for the ChangeLog
      • Fix indenting in examples  (e.g. in Rocael's robust web    development framework)
      • overthink Win2000 guidelines.  There are the native compiled packages from Maurizio, including everything from postgres, xotcl ....
    • It is desired to find a single person responsible for overworking the documentation, however, funding is unclear.

OpenACS Version 5.4 Agenda

  • DONE: HTML Strict (openacs core)
  • DONE: finish template::head (daveb)
  • DONE: test acs-mail-lite (complex send)
  • DONE: test notifications (complex send)
  • DONE: new XinHA release, get rid of RTE & HTMLarea, test on Safari
  • DONE: Form builder: add the ID attribute  to the form tag
  • DONE: acs-lang - keepLocalTranslationP to be removed
  • DONE search and intermedia-driver: move intermedia specific stuff to its package
  • DONE: acs-mail-lite - patch for mime::qp_encode bug


  • Split Xinha and TinyMCE into separate packages see:
  • Usability ("my account" page)
  • XHTML ?
  • Testing and documentation for recording automated tests using the firefox plugin and the upload feature for it new in automated testing. Probably needs some polishing and should be talked to with Quest who are getting into this.
  • Parameter Scope Patch 
  • Remove obsolete master template stuff (default and site master template in openacs-4/www, acs-subsite's group-master, and related CSS and images).  Probably in the version which follows 5.5 (probably 5.6).  Also remove the compat master stuff at the same time.

Things to merge into this page

Old 5.0 Roadmap  discussion 

Roadmap discussion 1 

 [Ideas for Boston 2006 Future of OpenACS discussion]

My previous attempt at collaborative roadmap 

A .LRN Roadmap 

Another .LRN Roadmap discussion 


What's on this page?

This page should include work that is planned on and has someone committed to working on it.

OpenACS/.LRN for Debian

Created by Héctor Romojaro, Stefan Sobernig, last modified by Gustaf Neumann 22 Mar 2019, at 11:14 PM




Packages of OpenACS  and .LRN  are now available for Debian GNU/Linux . We hope to facilitate the adoption by novices and the infrastructure deployment by professional users, both running Debian GNU/Linux  and its derivatives. Our packaging activity explicitly targets Debian GNU/Linux  stable , testing and unstable . Important dependencies are co-maintained with the Debian Tcl/Tk Maintainers .

See also OpenACS for Ubuntu.

Getting started

Please, review the section on supported distributions first.  Currently, the core packages (openacs, dotlrn) and their dependencies are included into the official Debian GNU/Linux  repositories.


  1. Run:

    apt-get update


  2. (optional) Provide for a PostgreSQL environment: If you don't have a PostgreSQL installation at hand, provide one. You do not need to care about setting up a concrete data base. This is automatically done by the OpenACS and dotlrn post-install instructions. For further PostgreSQL-related set-up issue, see ...
    apt-get install postgresql
    If you run a remote PostgreSQL instance, remember to allow for access of the PostgreSQL Administrator (postgres) and the openacs/dotlrn user from machine hosting your OpenACS/.LRN installation.
  3. Install the core packages and follow the on-screen instructions:
    # OpenACS
    apt-get install openacs
    ... or ...
    # .LRN
    apt-get install dotlrn   

After Install

  1. (optional) To change IP address and port of the instance, please edit the file:
    # OpenACS
    # dotLRN
  2. (optional) To control the instance using daemontools, please install the daemontools debian packages and follow the instructions on the file:

    # OpenACS
    # dotLRN


Next Steps, After Basic Installation (above)



Active contributors

  • Héctor Romojaro 
  • Stefan Sobernig
  • Avni M. Khatri
  • Carl R. Blesius

Packages status

Packages maintained by Debian Tcl/Tk Maintainers 


Packages co-maintained by OCT & Debian Tcl/Tk Maintainers 





Please, for getting in contact and reporting issues, consider ...

Documentation Project Plan (Approach 4)

Created by OpenACS community, last modified by Benjamin Brink 05 Oct 2018, at 10:02 PM

This is Approach 4 of the en:Documentation_Project as defined in Documentation_Project_Discussion.  Users benefit when they can read docs the way the brain likes to work. Contributions to various OpenACS topics that further the plan are welcome.


See Documentation history


to write superb documentation, so that users, developers and administrators of OpenACS installations can enjoy working with and using the system (with fewer headaches! =)


OpenACS documentation, a systems view as a collection of subsystems and their parts.

API Documentation: there are no plans to move the API docs to XoWiki. That should remain as is.

DocBook docs at: are evolving separately at en:New_Documentation_Process


Requirements is about setting specifications and milestones we can verify, and includes exploration of scenarios, use cases etc.

Here are documentation requirements for:

Available resources

  • volunteers dedicated to regularly managing and updating the documentation
  • other volunteers who contribute arguably more valuable documentation less frequently (such as magazine articles ;) (and may need some assistance etc. to have their work fit into docs well.)
  • website, including use of xowiki
  • open-source software, text editors, spell checkers, html code validators etc.
  • Approaches in docs management explored. See en:Documentation_Project_Discussion


Strategy is about creating an approach to doing work. It guides behavior and tactical decisions on the work effort.

Shape ongoing documentation efforts by using principles of continual improvement and following general requirements to re-engineer documentation production and management.

OpenACS documentation development is subject to constraints of the software project development and release methods and cycles (the section called “Using CVS with OpenACS”). Essentially, all phases of work may be active to accommodate the asynchronous nature of multiple subprojects evolving by the efforts of a global base of participants with culturally diverse time references and scheduling idiosyncrasies.

The documentation strategy is to use methods that inspire collaborating or obtaining guidance or feedback (peer review) to distribute the workload and increase the overall value of output for the OpenACS project.

subdivide by subsystems and how they are used (context). Why?

"..the human mind can only deal with a relatively small number of independent pieces of data at one time, but if data are chunked together in appropriate ways, the mind can perform higher order abstractions, and these in turn can be chunked together, with successive abstractions, until an entire complex situation is encompassed. The systems approach addresses this property of the human mind by providing strategies for the data gathering, chunking, and abstracting process." George G. Lendaris, On Systemness and the Problem Solver: Tutorial comments 1983.

XoWiki docs can use a systems strategy of multiple perspectives to help identify subsystems and how OpenACS works.

Each XoWiki page discusses a single topic.

These topics are pieced together by any number of other xowiki pages to present an ordered presentation of the topics with a common thread/topic connecting them.

For example, en:openacs-system-install is a page that links together the topics of installing the component software of Openacs. Similarly, each component software, such as en:aolserver, has its own view of some overlapping topics.

XoWiki documents organized by subsystems (and how they are used) are easy to update and maintain since there is only one place to put relevant information for a particular topic.

Pages are not encumbered by a maze of categories that tend to only address one or a few perspectives, since pages link to related pages, and a page that addresses each perspective can link to overlapping topics.

In an ideal world, XoWiki will be able to export a page and all the pages that link to it, to any depth of the linkage tree, to form one document. That way, innumerable documents, each with a valid perspective, can be built for a specific purpose.

Work Breakdown Structure

Or Objectives and Key Results (OKRs) is about explicitly stating the way to implement the strategy as a set of milestones and the methods to use.

Allow document writers to reference package API via api-doc by using package_url, or find the local package_id so a link can be supplied from the local documentation to current, up-to-date API and SQL docs, like: use links like this: /api-doc/index?about_package_key=acs-datetime The feature has been added to cvs head (OpenACS 5.3.x) so will be released soon.[DONE]

Iterate through each topic on each docbook page.

  • Port the docbook pages to xowiki manually, because it allows me to look at each part in details and separate to subsystem/object context. Here is the process:
  • Browse to docbook url (something in this tree:
  • View page source
  • Copy the relevant part of source
  • Paste that source to your favorite text editor (not word processor).
  • Edit the page source, removing DIV tags and TARGET="_blank" attributes. Look for any immediate way to improve the document, make additional edits, check for spelling etc.
  • In a browser, open or create the xowiki page. Choose "Source" to view source html. Be sure to make Name starting with "en:"
  • Paste edited source into the xowiki page, repeat editing if needed
  • Click "ok" to post the xowiki changes.
  • That's it! (repeat)

Example documentation outline in wiki

These pages contain links to other pages where items are discussed in context:

Name for/description
en:docs-end-user documentation for everyone
en:openacs-system end-user about OpenACS system, ties together much of the stuff below.
en:docs-end-user-reqs end-user doc requirements and checklist
en:docs-install installing OpenACS prerequisits
en:openacs-system-install installing OpenACS overview
en:openacs-system-install-redhat installing OpenACS on Redhat
en:docs-install-reqs installation- docs requirements and checklist
en:docs-admin administrators
en:docs-admin-reqs administration - doc requriments and checklist
en:docs-dev-tutorial tutorials for developers
en:docs-dev-tutorial-reqs developer tutorials - requirements and checklist
en:docs-eng developers
en:docs-eng-reqs developing - requirements and checklist

These pages describe various OpenACS subsystems, and link to external documents where possible and appropriate. Note that an "OpenACS system" en:openacs-system page that outlines the system and ties these together is part of the end-user docs.

Name subsystem of OpenACS
en:aolserver AOLserver
en:aolserver-install installing AOLserver
en:aolserver-admin administrating AOLserver
[en:naviserver] NaviServer
en:naviserver-openacs installing NaviServer
en:oracle Oracle relational database
en:oracle-install installing Oracle
[en:oracle-admin] administrating Oracle
en:postgresql PostgreSQL relational database
en:postgresql-install installing PostgreSQL
en:postgresql-admin administrating PostgreSQL
en:os-nix *nix operating system
en:os-nix-install installing an OS
en:tcl Tcl language
en:tcl-install installing Tcl
en:openacs-subsystem OpenACS subsystem (layer)
en:openacs-subsystem-install install OpenACS

Auxiliary systems

en:ide-emacs gnu emacs as IDE
[en:ide-emacs-nxml] gnu emacs nXML Mode
[en:ide-emacs-psgml] gnu emacs PSGML Mode
en:ide-vi vi/vim as IDE


This is where we measure how well this plan was implemented. Success is measured by

  • A) verifying if the project has met the established goals and requirements, and
  • B) reviewing for ongoing problem areas etc.

Observations then help to modify the plan for the next documentation revision.

OpenACS follows verification through different means on different projects, but in all cases, the OpenACS community verifies the project as a success through feedback including bug reports, user and administrator comments, and code changes.

Related links and sources 

Dynamic Object Types and Attributes

Created by Malte Sussdorff, last modified by Gustaf Neumann 08 Jul 2018, at 11:07 AM

The goal of this page is to come up with a generic specification for an OpenACS core package that allows us to create object types using a WebUI and assign attributes to it. Furthermore, using this interface it should be possible to extend any other existing object type and seamlessly have it work in the respective pages without many changes needed.

 At the moment three different approaches exist to tackle (part) of this problem. This needs to be modified so we only get one version out of it. The three approaches are:


ams is used by contacts as its primary storage for attributes. It's primary focus is to easily extend existing object types with attributes.

AMS stores the additional attributes in a meta table system from which it retrieves the values again. This allows flexibility as you can reuse attributes easily and you do not have to create database statements when you want to extend and object type. Additionally you do not need one table per object type and you are not limited by the number of rows a table can have as a maximum.

Dynamic Types

Dynamic Types is used by project manager to enhance the tasks and the project attributes. It is furthermore used in custom applications by cognovís, Solution Grove and xarg Ltd. 

(DAVEB) In general, Lee and I also want to support,

  • Multiple storage models (generic, type-specific table)
  • Defining forms for multiple objects on one "page"
  • Defining forms that are not associated with an object

So I think we have the same ideas. This is where I think the form definition framework needs to be separate from the object type, so we can define a form and where the data goes, whether it is one object, multiple objects, or no object. We definitely should extend, and improve the existing acs_attributes table and features to support what we need. 



Dynfields (formerly known as flexbase) is the dynamic attribute system used by ]po[ (formerly known as Project/Open) and based of AMS while trying to get the good things from dynamic types in it as well. 



The attribute definition should be strored in AMS (AMS or ACS? DAVEB) attributes and the object types should be acs object types to make it easier and reuse existing functionality. Once we agree on a single system, the need for extension of ams_attributes tables done by the exisiting packages won't be needed anymore, as we could generically extend ams_attributes.

As for the attributes itself, we have two storage options. BOTH should be implemented and defined in the Attribute generation where it is actually stored.

Metadata Storage

 This is the way AMS stores it's data. You have ams tables that hold the attributes and depending on the settings of the attribute the options (if multiple choice) or the plain value. Additionally support for address and telephone number object type exists. As you can see this actually allows a hierarchy of object types (an object type can exist out of multiple other object types and not only the ones provided by the database).



  • On the plus side is it's flexibility (no need to make changes to the database tables) and the ability to use subtypes.
  • Additionally you can quickly add and remove options from a multiple choice attribute.




  • A major drawback of this approach is the fact that the metadata tables can grow very large if you store all attributes in them (although in our CRM settings this so far was not an issue, knock on wood).
  • Additionally adding the attributes into database selects can take it's time (as the stored PL/SQL functions to retrieve an attribute are slower than just querying a field in a database table). On the other hand, if used with the caching mechanisms provided in AMS and using template::multirow::sort instead of having listbuilder sort in the database, things get considerably sped up.


Table( extension)s

Dynamic Types stores the attributes in the object_types table as defined in acs_object_types. Alternatively you could specify a different table to use for the storing of the attribute, although this will delute one of the main benefits of DT, the fast access to the data.


See AMS minus 


See AMS plus :-). 



The api should provide you with procedures to


  • Create a new object type
  • Extend an existing object type with attributes
  • For each attribute let you define where you want to store it and of what type the attribute is
  • Choose the widget for displaying the attribute
  • Retrieve the attributes value both in Tcl and pl/sql
  • Extend ad_from and template::list so that it automatically allows you to display all attributes
  • Support pages / ams_lists, to limit the display in ad_form and template::list to the attributes in the list
  • Save all attributes of an object_type at once (needed when we deal with subtypes)
  • Support for alternative storage areas for subtypes. E.g. postal-addresses is stored in the postal_address table. Same for ]po[ attributes.
  • Support for external storage areas. Especially in the corporate world they have their own applications storing data. Instead of synchronizing it manually, have acs-attributes use the external storage.


A page in the context here (and please change it if you have a better idea) is what AMS calls lists. It allows you to group multiple attributes per object type so they can be entered in one go. As an example in contacts you can use pages for each group a person (object_type) belongs in, so depending on the group membership, only certain attributes can be edited or displayed. Additionally permissions can be granted on a page basis, therefore allowing only admins to enter admin relevant data. Though in contacts we do have need to provide permissions on a per page/object level (e.g all users can edit their own data except for attributes xyz stored in the pages abc), I don't think this is useful in a general way.

A second use case are projects, where you can have additional attributes depending on the project type. Combined with workflow this gives you a powerful tool where you can have a project undergo various stages and in each stage other attributes are relevant to be filled out, though the project itself is never losing the value of one of it's attributes in the process.

Furthermore, pages should support headings and allow the setting of required and default values for attributes (so the required tag and the default value can differ for an attribute, depending on which page it is used).

Additionally we should think about support for using display, template::list and form templates for each page, so we could modify how a page of attributes is displayed to a user.

Last but not least, we might want to have pages support display and editing of attributes from multiple object_types on the same page.

User Interface

A user interface needs to exist so you can easily create a new object type and add attributes to existing object types. Furthermore support for creating pages needs to be there so you can limit the number of attributes displayed in a form/list and define the order in which they are displayed (form_entry_order, form_display_order, list_display_order, default_list_sort_order).


Listbuilder would need to change so we could (optional setting in page) allow the user to define which elements of a page he wants to have in his list. Furthermore, the sort order needs to take into account that we might have to sort by an attribute that is stored in metadata storage, so we would have to sort the list e.g.with template::list::sort. Last but not least, to make it easy for users, we should not have to rewrite every template::list statement to allow the display of additional attributes, so dynamic attribute support should hopefully come out of the box. Okay, this might just be too much of a goal, especially taking into account that lists usually combine multiple object types into one.


ad_form would need to be amended so it supports pages, meaning if called with a page name it will display all the attribute of the page. This is in addition to any elements already defined on the page, though for obvious reasons it should not display the same page name twice. If called with multiple pages, display the attributes of each page, beginning with the first in the list and making sure that you are not displaying a page twice. This is useful if you have in contacts a person in multiple groups (which relates to multiple pages) but you want to edit the attributes of all the pages of the groups he is a member in at the same time 

Official Test Servers

Created by Gustaf Neumann, last modified by Gustaf Neumann 19 Oct 2017, at 11:53 AM

Currently none

{done} OpenACS 5.3.x releases

Created by Rocael Hernández Rizzardini, last modified by Gustaf Neumann 19 Oct 2017, at 11:53 AM

OpenACS 5.3.x Releases

Update: OpenACS 5.3.0a1 is available for download or by checking out openacs-5-3-0a1 tag from CVS. Work continues on the oacs-5-3 branch in CVS

The main goal is to have acs-core to pass all the automated tests (PG 8.1.x & Oracle 9i).

We plan to branch for oacs-5-3 in September 2006. 

Many bug stomp where we actually create, fix, update tests for acs-core has been done. 

Bug-stomp: 21-22 sept. 06. Focus on have all the actual test pass for acs-core (no more new test), plus start classifying the bugs in the bug-tracker. Based on the results of this bug-stomp we'll decide when to branch and what should be included (bug-fixes) in next release.


Check the Official Test Servers



OpenACS Release Status

Created by Dave Bauer, last modified by Gustaf Neumann 08 Aug 2017, at 12:13 AM

Current Stable Release

5.9.1 Released 2017-08-08

Download OpenACS 5.9.1 Core 

Download OpenACS 5.9.1 Full 

Previous Releases

5.9.0 Released 2015-12-01

Download OpenACS 5.9.0 

5.8.1 Released 2014-10-25

Download OpenACS 5.8.1 

5.8.0 Released 2013-08-30 

Download OpenACS 5.8.0 

5.7.0 Released 2013-07-17 

Download OpenACS 5.7.0 

5.6.0 Released 2010-09-22 

Download OpenACS 5.6.0 

5.5.0 Released 2009-06-22 

Download OpenACS 5.5.0 

5.4.3 Released  2008-11-26 (No more releases on the 5.4 branch)

Download OpenACS 5.4.3 

5.4.2 Released  2008-06-08

Download OpenACS 5.4.2 

5.4.1 Released  2008-04-07

Download OpenACS 5.4.1 

5.4.0 Released  2008-02-07

Download OpenACS 5.4.0 

5.3.2 Released  2007-07-18 (No more releases on the 5.3 branch)

Download OpenACS 5.3.2 

Next Bugfix Release 


Next Major Release


TODO list for next release

Incoming E-Mail

Created by Malte Sussdorff, last modified by Benjamin Brink 05 Jul 2017, at 04:37 AM

Incoming E-Mail in OpenACS works with the latest version of acs-mail-lite in a general fashion using callbacks.

The original version of this documentation is found via at:

We will take a look on what needs to be done to get incoming e-mail working and then continue on to see how packages can benefit.

Project notes:  ACS Mail Lite sends via SMTP which permits the use of an external server to handle email. For scalability, consider expanding the incoming E-mail paradigm to likewise use Tcllib's imap4  or NaviServer&#39;s nsimap  so that most all email can be handled on separate servers. 

Install incoming E-Mail

First, one must have an understanding of postfix basics. See .

These instructions use the following example values:

  • hostname:
  • oacs user: service0
  • OS: Linux
  • email user: service0
  • email's home dir: /home/service0
  • email user's mail dir: /home/service0/mail

Important: The email user service0 does not have a ".forward" file. This user is only used for running the OpenACS website. Follow careful use of email rules by following strict guidelines to avoid email looping back unchecked.

For postfix, the email user and oacs user do not have to be the same. Furthermore, postfix makes distinctions between virtual users and user aliases .  Future versions of this documentation should use examples with different names to help distinguish between standard configuration examples  and the requirements of ACS Mail Lite package.

Postfix configuration parameters:


inet_interfaces=$myhostname, localhost


virtual_alias_domains  =

virtual_maps =regexp:/etc/postfix/virtual


Here is the sequence to follow if installing email service on system for first time. If your system already has email service, adapt these steps accordingly:

  1. Install postfix
  2. Install smtp (for postfix)
  3. Install metamail (for acs-mail-lite)
  4. Edit /etc/postfix/
  5. Edit /etc/postfix/virtual   Add a regular expression to filter relevant incoming emails for processing by OpenACS. service0
  6. Edit /etc/postfix/ - uncomment this line so postfix listens to emails from internet
    smtp inet n - n - - smtpd
  7. Create a mail directory as service0
    mkdir /home/service0/mail
  8. Configure ACS Mail Lite parameters
    BounceMailDir: /home/service0/mail
    EnvelopePrefix: bounce

    The EnvelopePrefix is for bounce e-mails only.

    NOTE: Parameters should be renamed: 
    BounceDomain to IncomingDomain
    BounceMailDir to IncomingMaildir
    EnvelopePrefix to BouncePrefix reflect that acs-mail-lite is capable of dealing with other types of incoming e-mail.

    Furthermore, setting IncomingMaildir parameter clarifies that incoming email handling is setup. This is useful for other packages to determine if they can rely on incoming e-mail working (e.g. to set the reply-to email to an  e-mail address which actually works through a callback if the IncomingMaildir parameter is enabled).
  9. Configure Notifications parameters
    EmailReplyAddressPrefix: notification
    EmailQmailQueueScanP: 0

    We want acs-mail-lite incoming handle the Email Scanning, not each package separately.
    Configure other packages likewise
  10. Invoke postmap in OS shell to recompile virtual db:
    postmap /etc/postfix/virtual
  11. Restart Postfix. 
    /etc/init.d/postfix restart
  12. Restart OpenACS


Processing incoming e-mail


A sweeper procedure like acs_mail_lite::load_mails  should:

  1. scan the e-mails which are in the IncomingMaildir directory on a regular basis.
  2. check if any email came from an auto mailer.
  3. Parse new ones, and
  4. process them by firing off callbacks.

Vinod has made a check for auto mailers by using procmail as follows. Maybe we could get this dragged into Tcl code (using regexp or a Procmail recipe parser) instead, thereby removing the need for setting up procmail in the first place.

Revised procmail filters:

:0 w * ^subject:.*Out of Office AutoReply /dev/null 
:0 w * ^subject:.*Out of Office /dev/null :0 w * ^subject:.*out of the office /dev/null 
:0 w * ^subject:.*NDN /dev/null :0 w * ^subject:.*[QuickML] Error: /dev/null 
:0 w * ^subject:.*autoreply /dev/null :0 w * ^from.*mailer.*daemon /dev/null

To make things granular a separate parsing procedure should deal with loading the e-mail into the Tcl interpreter and setting variables in an array for further processing.

ad_proc parse_email { 
} { 

An email is split into several parts: headers, bodies and files.

The headers consists of a list with header names as keys and their corresponding values. All keys are lower case.

The bodies consists of a list with two elements: content-type and content.

The files consists of a list with three elements: content-type, filename and content.

An array with all the above data is upvarred to the caller environment.

Processing an email should result in an array like this:


  • message_id
  • subject
  • from
  • to
  • date
  • received
  • references
  • in-reply-to
  • return-path
  • .....


  • X-Mozilla-Status
  • X-Virus Scanned
  • .....

We do not know which headers are going to be available in the e-mail. We set all headers found in the array. The callback implementation then checks if a certain header is present or not.

        #get all available headers
        set keys [mime::getheader $mime -names]
        set headers [list]

        # create both the headers array and all headers directly for the email array
        foreach header $keys {
            set value [mime::getheader $mime $header]
            set email([string tolower $header]) $value
            lappend headers [list $header $value]
        set email(headers) $headers


An e-mail usually consists of one or more bodies. With the advent of complex_send, OpenACS supports sending of multi-part e-mails which are needed if you want to send out and e-mail in text/html and text/plain (for old mail readers).

switch [mime::getproperty $part content] {
     "text/plain" {
          lappend bodies [list "text/plain" [mime::getbody $part]]
     "text/html" {
          lappend bodies [list "text/html" [mime::getbody $part]]


OpenACS supports tcllib mime functions. Getting incoming files to work is a matter of looking for a part where there exists a "Content-disposition" part. All these parts are file parts. Together with scanning for email bodies, code looks something like this:

        set bodies [list]
        set files [list]
        #now extract all parts (bodies/files) and fill the email array
        foreach part $all_parts {

            # Attachments have a "Content-disposition" part
            # Therefore we filter out if it is an attachment here
            if {[catch {mime::getheader $part Content-disposition}]} {
                switch [mime::getproperty $part content] {
                    "text/plain" {
                        lappend bodies [list "text/plain" [mime::getbody $part]]
                    "text/html" {
                        lappend bodies [list "text/html" [mime::getbody $part]]
            } else {
                set encoding [mime::getproperty $part encoding]
                set body [mime::getbody $part -decode]
                set content  $body
                set params [mime::getproperty $part params]
                if {[lindex $params 0] == "name"} {
                    set filename [lindex $params 1]
                } else {
                    set filename ""

                # Determine the content_type
                set content_type [mime::getproperty $part content]
                if {$content_type eq "application/octet-stream"} {
                    set content_type [ns_guesstype $filename]

                lappend files [list $content_type $encoding $filename $content]
        set email(bodies) $bodies
        set email(files) $files

Note that the files ie attachments are actually stored in the /tmp directory from where they can be processed further. It is up to the callback to decide if to import the file into OpenACS or not. Once all callbacks have been fired files in /tmp will have to be deleted again though.

Firing off callbacks 

Now that we have the e-mail parsed and have an array with all the information, we can fire off the callbacks. The firing should happen in two stages.

The first stage is where we support a syntax like "".

Second, incoming e-mail could look up the object_type, and then call the callback implementation specific to this object_type. If object_type = 'content_item', use content_type instead. 

ad_proc -public -callback acs_mail_lite::incoming_object_email { -array:required -object_id:required } { }

callback acs_mail_lite::incoming_object_email -impl $object_type -array email -object_id $object_id


ad_proc -public -callback acs_mail_lite::incoming_object_email -impl user {



} {

    Implementation of mail through support for incoming emails

} {

    # get a reference to the email array

    upvar $array email

 # make the bodies an array

        template::util::list_of_lists_to_array $email(bodies) email_body

        if {[exists_and_not_null email_body(text/html)]} {

            set body $email_body(text/html)

        } else {

            set body $email_body(text/plain)


        set reply_to_addr "[party::get_by_email $email(from)]@[ad_url]"

        acs_mail_lite::complex_send \

            -from_addr $from_addr \

            -reply_to $reply_to_addr \

            -to_addr $to_addr \

            -subject $email(subject) \

            -body $body \

            -single_email \



Object id based implementations are useful for automatically generating "reply-to" addresses. With ProjectManager and Contacts object_id is also handy, because Project / TaskID is prominently placed on the website. If you are working on a task and you get an e-mail by your client that is related to the task, just forward the email to "$" and it will be stored along with the task. Highly useful :).

Obviously you could have implementations for:

  • forums_forum_id: Start a new topic

  • forums_message_id: Reply to an existing topic

  • group_id: Send an e-mail to all group members

  • pm_project_id: add a comment to a project

  • pm_task_id: add a comment to a task and store the files in the projects folder (done)


Once the e-mail is dealt with in an object oriented approach we are either done with the message (an object_id was found in the to address) or we need to process it further.

ad_proc -public -callback acs_mail_lite::incoming_email {
} {
array set email {}
parse_email -file $msg -array email
set email(to) [parse_email_address -email $email(to)]
set email(from) [parse_email_address -email $email(from)]

# We execute all callbacks now
callback acs_mail_lite::incoming_email -array email

For this a general callback should exist which can deal with every leftover e-mail and each implementation will check if it wants to deal with this e-mail. How is this check going to happen? As an example, a package could have a prefix, as is the case with bounce e-mails as handled in acs_mail_lite::parse_bounce_address (see below):

ad_proc -public -callback acs_mail_lite::incoming_email -impl acs-mail-lite {
} {
    @param array        An array with all headers, files and bodies. To access the array you need to use upvar.
    @param package_id   The package instance that registered the prefix
    @return             nothing
} {
    upvar $array email

    set to [acs_mail_lite::parse_email_address -email $email(to)]
    ns_log Debug "acs_mail_lite::incoming_email -impl acs-mail-lite called. Recepient $to"

    util_unlist [acs_mail_lite::parse_bounce_address -bounce_address $to] user_id package_id signature
    # If no user_id found or signature invalid, ignore message
    # Here we decide not to deal with the message anymore

    if {[empty_string_p $user_id]} {
        if {[empty_string_p $user_id]} {
            ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: No equivalent user found for $to"
        } else {
            ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Invalid mail signature $signature"
    } else {
        ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Bounce checking $to, $user_id"
        if { ![acs_mail_lite::bouncing_user_p -user_id $user_id] } {
            ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Bouncing email from user $user_id"
            # record the bounce in the database
            db_dml record_bounce {}
            if {![db_resultrows]} {
                db_dml insert_bounce {}

Alternatively we could just check the whole to address for other things, e.g. if the to address belongs to a group (party)

ad_proc -public -callback acs_mail_lite::incoming_email -impl contacts_group_mail {
    {-package_id ""}
} {
    Implementation of group support for incoming emails
    If the to address matches an address stored with a group then send out the email to all group members

     @author Malte Sussdorff (
     @creation-date 2005-12-18

     @param array        An array with all headers, files and bodies. To access the array you need to use upvar.
     @return             nothing
} {

    # get a reference to the email array
    upvar $array email

    # Now run the simplest mailing list of all
    set to_party_id [party::get_by_email -email $email(to)]
    if {[db_string group_p "select 1 from groups where group_id = :to_party_id" -default 0]} {
        # make the bodies an array
        template::util::list_of_lists_to_array $email(bodies) email_body
        if {[exists_and_not_null email_body(text/html)]} {
            set body $email_body(text/html)
        } else {
            set body $email_body(text/plain)
        acs_mail_lite::complex_send \
            -from_addr [lindex $email(from) 0] \
            -to_party_ids [group::get_members -group_id $to_party_id] \
            -subject $email(subject) \
            -body $body \
            -single_email \


Or check if the to address follows a certain format.

ad_proc -public -callback acs_mail_lite::incoming_email -impl contacts_mail_through {
    {-package_id ""}
} {
    Implementation of mail through support for incoming emails
    You can send an e-amil through the system by sending it to
    The email will be send from your system and if mail tracking is installed the e-mail will be tracked.

    This allows you to go in direct communication with a customer using you standard e-mail program instead of having to go to the website.

    @author Malte Sussdorff (
    @creation-date 2005-12-18
    @param array        An array with all headers, files and bodies. To access the array you need to use upvar.
    @return             nothing
} {
    # get a reference to the email array
    upvar $array email

    # Take a look if the email contains an email with a "#"
    set pot_email [lindex [split $email(to) "@"] 0]
    if {[string last "#" $pot_email] > -1} {

 Alternatives to this are:

  • ${component_name} (where component_name could be openacs or dotlrn or contacts or whatever), to store a new bug in bug-tracker
  • (to do mail-through using the user name, which allows you to hide the actual e-mail of the user whom you are contacting).


Once all callbacks have been fired off,  e-mails need to be deleted from the Maildir directory and files which have been extracted need to be deleted as well from the /tmp directory. 

User interface mockups

Created by Dave Bauer, last modified by Benjamin Brink 30 Jun 2017, at 05:09 PM

NameContent TypeLast ModifiedBy UserSize (Bytes)
file-upload-mockups.pdfapplication/pdf2017-06-30 17:09:01+02Benjamin Brink161631

Activity Graph

Created by Gustaf Neumann, last modified by Benjamin Brink 30 Jun 2017, at 07:12 AM

You must login to see the activity-graph

Next Page
previous May 2019
Sun Mon Tue Wed Thu Fri Sat
28 29 30 1 2 (1) 3 4
5 6 7 8 9 10 11
12 13 (1) 14 (1) 15 16 17 18
19 20 21 22 (1) 23 24 25
26 27 28 29 30 31 1

Popular tags

17 , 5.9.0 , 5.9.1 , ad_form , ADP , ajax , aolserver , asynchronous , bgdelivery , bootstrap , bugtracker , CentOS , COMET , compatibility , CSP , CSRF , cvs , debian , emacs , engineering-standards , fedora , FreeBSD , guidelines , host-node-map , hstore , includelets , install , installation , installers , install-ns
No registered users in community xowiki
in last 30 minutes