Index: openacs-4/packages/image-magick/image-magick.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/image-magick.info,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/image-magick.info 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,28 @@ + + + + + Image Magick + Image Magick + f + t + + + Tom Ayles + Provides an interface to the ImageMagick image manipulation tools. + 2004-01-09 + London Borough of Camden + Provides an interface to the ImageMagick image manipulation tools. This is just a set of Tcl procedures that create and execute the appropriate command line. + + + + + + + + + + + + + Index: openacs-4/packages/image-magick/tcl/image-magick-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/tcl/image-magick-init.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/tcl/image-magick-init.tcl 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,33 @@ +ad_library { + This is free software distributed under the terms of the GNU General Public + License. Full text of the license is available from the GNU Project: + http://www.fsf.org/copyleft/gpl.html + + Initialises the Image Magick module. + + @author Tom Ayles (tom@beatniq.net) + @creation-date 2004-01-09 + @cvs-id $Id: image-magick-init.tcl,v 1.1 2005/08/31 17:05:18 leed Exp $ +} + +set tmp_dir [parameter::get_from_package_key -package_key image-magick \ + -parameter TmpDir] + +# make temporary directory if not present + +if {![file exists $tmp_dir]} { + if {[catch {file mkdir $tmp_dir} err]} { + ns_log Error "Error preparing TmpDir image-magick may not function correctly, message was: $err" + } + + if {![file writable $tmp_dir]} { + ns_log Error "$tmp_dir is not writable, image-magick may not function correctly" + } +} + +if {[parameter::get_from_package_key -package_key image-magick \ + -parameter ClearTmpDirOnStartupP]} { + set files [glob "${tmp_dir}/*"] + ns_log Notice "ImageMagick deleting temporary files: $files" + eval "file delete [join $files]" +} Index: openacs-4/packages/image-magick/tcl/image-magick-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/tcl/image-magick-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/tcl/image-magick-procs-oracle.xql 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,79 @@ + + + + oracle + + + + + begin + :1 := image.new ( + name => :name, + parent_id => :parent_id, + item_id => :item_id, + revision_id => :revision_id, + creation_user => :user_id, + creation_ip => :user_ip, + title => :name, + description => :description, + mime_type => :mime_type, + relation_tag => :relation_tag, + is_live => :live_p, + filename => :cr_file, + height => :height, + width => :width, + file_size => :file_size + ); + end; + + + + + + + + begin + :1 := image.new_revision ( + item_id => :item_id, + revision_id => :revision_id, + creation_user => :user_id, + creation_ip => :user_ip, + title => :name, + description => :description, + mime_type => :mime_type, + is_live => :live_p, + filename => :cr_file, + height => :height, + width => :width, + file_size => :file_size + ); + end; + + + + + + + + begin + content_revision.del (:revision_id); + end; + + + + + + + + begin + content_item.del (:item_id); + end; + + + + + Index: openacs-4/packages/image-magick/tcl/image-magick-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/tcl/image-magick-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/tcl/image-magick-procs-postgresql.xql 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,83 @@ + + + + postgresql7.2 + + +BEGIN + PERFORM image__new ( + :name, -- name + :parent_id, -- parent_id + :item_id, -- item_id + :revision_id, -- revision_id + :mime_type, -- MIME + :user_id, -- user ID + :user_ip, -- user IP + :relation_tag, -- relation tag (?) + :name, -- title + :description, -- description + :live_p, -- is live? + current_timestamp,-- publish time + :cr_file, -- path + :file_size, -- file size + :height, -- height + :width -- width + ); + + RETURN null; +END; + + + +BEGIN + PERFORM content_revision__new ( + :name, -- title + :description, -- description + current_timestamp, -- publish date + :mime_type, -- MIME type + null, -- language + null, -- data + :item_id, -- item ID + :revision_id, -- revision ID + current_timestamp, -- creation date + :user_id, -- creation user + :user_ip -- creation IP + ); + + INSERT INTO images + (image_id, height, width) + VALUES + (:revision_id, :height, :width); + + UPDATE cr_revisions SET + content_length = :file_size, + content = :cr_file + WHERE revision_id = :revision_id; + + IF :live_p = 't' THEN + PERFORM content_item__set_live_revision( :revision_id ); + END IF; + + RETURN null; +END; + + + +BEGIN + PERFORM content_revision__delete(:revision_id); + RETURN null; +END; + + + +BEGIN + PERFORM content_item__delete(:item_id); + RETURN null; +END; + + + Index: openacs-4/packages/image-magick/tcl/image-magick-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/tcl/image-magick-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/tcl/image-magick-procs.tcl 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,337 @@ +ad_library { + This is free software distributed under the terms of the GNU General Public + License. Full text of the license is available from the GNU Project: + http://www.fsf.org/copyleft/gpl.html + + Provides a set of procedures that encapsulate the Image Magick command + line image manipulation tools. + + @author Tom Ayles (tom.ayles@dsl.pipex.com) +} + +namespace eval ::ImageMagick {} + +ad_proc -private ::ImageMagick::bin_path { +} { + set bin_path [parameter::get_from_package_key \ + -package_key {image-magick} \ + -parameter {bin_path}] + if ![regexp /$ $bin_path] { + append bin_path / + } + return $bin_path +} + +ad_proc -public ::ImageMagick::convert_path { +} { + Returns the full path to the ImageMagick convert binary. +} { + return "[bin_path]convert" + +} + +ad_proc -public ::ImageMagick::identify_path { +} { + Returns the full path to the ImageMagick identify binary. +} { + return "[bin_path]identify" +} + +ad_proc -public ::ImageMagick::convert { + {-options {}} + {-geometry {}} + {-output_format {}} + input_file + output_file +} { + Invokes the ImageMagick convert command with the given arguments. + Ultimately, all options to convert will be encapsulated as switch + parameters to this procedure, and validation can be done on that. + However, until this is done, the options parameter + can be used to specify arbitrary extra parameters. + + @param options A list of extra options to pass to convert + @param output_format The output format to use + @param input_file The full path to the input file + @param output_file The full path to the output file +} { + set args [list] + foreach option $options { + lappend args $option + } + if ![empty_string_p $output_format] { + set output_file "${output_format}:${output_file}" + } + if ![empty_string_p $geometry] { + lappend args {-geometry} $geometry + } + lappend args $input_file + lappend args $output_file + eval "exec [convert_path] [join $args]" +} + +ad_proc -public ::ImageMagick::tmp_dir { +} { + Returns the ImageMagick temporary directory (with trailing slash). +} { + set tmp_dir [parameter::get_from_package_key \ + -package_key image-magick -parameter TmpDir] + if { ![regexp {/$} $tmp_dir] } { append tmp_dir / } + return $tmp_dir +} + +ad_proc -public ::ImageMagick::tmp_file { +} { + Creates a new temporary file name. + @return The full path to the temporary file location. +} { + return "[tmp_dir][ns_mktemp imXXXXXX]" +} + +ad_proc -public ::ImageMagick::delete_tmp_file { + filename +} { + Tests the path is valid and deletes the file. +} { + set filename [expand_tmp_file $filename] + if {![validate_tmp_file $filename]} { + error "$filename is not an ImageMagick tmp file" + } + file delete $filename +} + +ad_proc -private ::ImageMagick::shorten_tmp_file { + filename +} { +} { + set exp "^[tmp_dir](im\[0-9A-Za-z\]{6})$" + regexp $exp $filename match filename + return $filename +} + +ad_proc -private ::ImageMagick::expand_tmp_file { + filename +} { + Returns the full path to the temporary file. If the filename passed is + is just the filename (without full path), the temporary directory is + prepended. If its already the full path, its just returned. No validation + is performed. +} { + if { ![regexp {^/} $filename] } { + set filename "[tmp_dir]${filename}" + } + return $filename +} + +ad_proc -private ::ImageMagick::validate_tmp_file { + filename +} { + Checks the given filename is a geniune temporary file. +} { + set filename [expand_tmp_file $filename] + set exp "^[tmp_dir]im\[0-9A-Za-z\]{6}$" + return [regexp $exp $filename] +} + +ad_proc -public ::ImageMagick::serve_tmp_file { + filename +} { + Serves the given file, having first validated that it is a genuine tmp + file (and not, say, /etc/passwd). The filename passed in can be either + the full path to the file, or just the filename in the ImageMagick + temporary directory. +} { + set filename [expand_tmp_file $filename] + if { ![validate_tmp_file $filename] } { + ad_return_complaint 1 {
  • The specified image name is invalid
  • } + } else { + ns_returnfile 200 image/png $filename + } +} + +ad_proc -public ::ImageMagick::identify { + file +} { +

    Identifies attributes of the file specified. This currently supports + the following attributes:

    +
    +
    geometry_width
    The width of the image, pixels +
    geometry_height
    The height of the image, pixels +
    format
    The format of the image, eg PNG +
    format_pretty
    The pretty format, eg Portable Network Graphics +
    file_size
    The size of the file +
    + + @param file The file to identify + @return An array of attribute-value pairs, as described above. +} { + set id_str [exec [identify_path] {-verbose} $file] + if ![regexp \ + {[Gg]eometry: +([0-9]+)x([0-9]+)} \ + $id_str match id(geometry_width) id(geometry_height)] { + error {Failed to extract geometry information} + } + if ![regexp \ + {[Ff]ormat: ([A-Za-z]+\+?) \((.+)\)} \ + $id_str match id(format) id(format_pretty)] { + error {Failed to extract format information} + } + set id(file_size) [file size $file] + + return [array get id] +} + +namespace eval ::ImageMagick::util {} + +ad_proc -public ::ImageMagick::util::create_image_item { + {-file:required} + {-revision_id {}} + {-item_id {}} + {-parent_id {}} + {-name {}} + {-description {}} + {-user_id {}} + {-user_ip {}} + {-relation_tag {none}} + {-live_p {t}} + {-mime_type {}} +} { + Creates a new image item in the content repository. + + @param revision_id Override the ID to use for the image revision + @param item_id Override the ID to use for the image item + @param parent_id The ID of the parent object of this image (default null) + @param name The name of the image revision (defaults to 'image-x' where x is revision ID) + @param description The description of the image revision + @param user_id The ID of the creating user (defaults to [ad_conn user_id]) + @param user_ip The IP of the creating user (defaults to [ns_conn peeraddr]) + @param relation_tag The relation tag (? - defaults to 'none') + @param live_p Whether the revision is set live (in 't', 'f') + @param mime_type The MIME type of the image (default is to guess) + @return The image item ID +} { + foreach var {item_id revision_id} { + if [empty_string_p [set $var]] { + set $var [db_nextval acs_object_id_seq] + } + } + if [empty_string_p $user_id] { set user_id [ad_conn user_id] } + if [empty_string_p $user_ip] { set user_ip [ns_conn peeraddr] } + if [empty_string_p $name] { set name "image-$revision_id" } + + # process empty string => db_null (no need, I think, but correct to do so) + foreach var {description parent_id relation_tag} { + if [empty_string_p [set $var]] { + set $var [db_null] + } + } + + # test file for existence, checking in tmp directory if needed + if {![file readable $file]} { + set _file $file + set file [ImageMagick::expand_tmp_file $file] + if {![file readable $file]} { + error "Couldn't open $_file for reading" + } + } + + array set id [ImageMagick::identify $file] + + set file_size $id(file_size) + set width $id(geometry_width) + set height $id(geometry_height) + + if [empty_string_p $mime_type] { + # kludgy, but will work for most image formats + set mime_type "image/[string tolower $id(format)]" + } + + # create a CR file for the image + set cr_file [cr_create_content_file \ + $item_id $revision_id \ + $file] + # stick a reference to this file in the DB + db_exec_plsql create {} + + return $item_id +} + +ad_proc -public ::ImageMagick::util::revise_image { + {-file:required} + {-item_id:required} + {-revision_id {}} + {-name {}} + {-description {}} + {-user_id {}} + {-user_ip {}} + {-mime_type {}} + {-live_p {t}} +} { + Creates a new revision of an image in the content repository. Default + values are as for create_image. + + @param file The image file to use + @param item_id The image item to revise + @param revision_Id Override the revision ID + @param name The revision name + @param description The revision description + @param user_id The ID of the creating user + @param user_ip The IP of the creating user + @param mime_type The MIME type of the image + @param live_p Whether to set the new revision to be the live revision + @return The new revision ID +} { + if [empty_string_p $revision_id] { + set revision_id [db_nextval acs_object_id_seq] + } + if [empty_string_p $user_id] { set user_id [ad_conn user_id] } + if [empty_string_p $user_ip] { set user_ip [ns_conn peeraddr] } + if [empty_string_p $name] { set name "image-$revision_id" } + if [empty_string_p $description] { set description [db_null] } + + # test file for existence, checking in tmp directory if needed + if {![file readable $file]} { + set _file $file + set file [ImageMagick::expand_tmp_file $file] + if {![file readable $file]} { + error "Couldn't open $_file for reading" + } + } + + array set id [ImageMagick::identify $file] + + set file_size $id(file_size) + set width $id(geometry_width) + set height $id(geometry_height) + + if [empty_string_p $mime_type] { + # kludgy, but will work for most image formats + set mime_type "image/[string tolower $id(format)]" + } + + # create a CR file for the image + set cr_file [cr_create_content_file \ + $item_id $revision_id \ + $file] + + db_exec_plsql revise {} + + return $revision_id +} + +ad_proc -public ImageMagick::util::delete_revision { + revision_id +} { + Deletes a CR revision. This is just a thin wrapper for + content_revision__delete at the DB level. +} { + db_exec_plsql del {} +} + +ad_proc -public ImageMagick::util::delete_item { + item_id +} { + Deletes a CR item. This is just a thin wrapper for content_item__delete. +} { + db_exec_plsql del {} +} Index: openacs-4/packages/image-magick/www/doc/design.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/www/doc/design.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/www/doc/design.html 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,309 @@ + + + + + + Detailed Design Documentation Template + + + + + + + + + + + +

    Detailed Design Documentation Template

    + +

    By You

    + + + +

    Start Note

    + +

    NOTE: Some of the sections of this template +may not apply to your package, e.g. there may be no user-visible UI +elements for a component of the OpenACS Core. Furthermore, it may be +easier in some circumstances to join certain sections together, +e.g. it may make sense to discuss the data model and transactions API +together instead of putting them in separate sections. And on +occasion, you may find it easier to structure the design discussion by +the structure used in the requirements document. As this template is +just a starting point, use your own judgment, consult with peers when +possible, and adapt intelligently.

    + +

    Also, bear in mind the audience for detailed +design: fellow programmers who want to maintain/extend the software, +AND parties interested in evaluating software quality.

    +
    + + +

    Essentials

    + +

    When applicable, each of the following items +should receive its own link:

    + + +
    + + +

    Introduction

    + +

    This section should provide an overview of +the package and address at least the following issues:

    + + + +

    Also worthy of treatment in this section:

    + + + +

    Note: it's entirely possible that a discussion of what a package is +not intended to do differs from a discussion of future improvements +for the package.

    +
    + + +

    Historical Considerations

    + +

    For a given set of requirements, typically +many possible implementations and solutions exist. Although +eventually only one solution is implemented, a discussion of the +alternative solutions canvassed - noting why they were rejected - +proves helpful to both current and future developers. All readers +would be reminded as to why and how the particular solution developed +over time, avoiding re-analysis of problems already solved.

    +
    + + +

    Competitive Analysis

    + +

    Although currently only a few package +documentation pages contain a discussion of competing software, +(e.g. chat, portals), this section should be present whenever such +competition exists.

    + + + +

    Note that such a discussion may differ from a discussion of a +package's potential future improvements.

    +
    + + +

    Design Tradeoffs

    + +

    No single design solution can optimize every +desirable software attribute. For example, an increase in the security +of a system will likely entail a decrease in its ease-of-use, and an +increase in the flexibility/generality of a system typically entails a +decrease in the simplicity and efficiency of that system. Thus a +developer must decide to put a higher value on some attributes over +others: this section should include a discussion of the tradeoffs +involved with the design chosen, and the reasons for your +choices. Some areas of importance to keep in mind are:

    + +

    Areas of interest to users:

    + + + +

    Areas of interest to developers:

    + +
    + + +

    API

    + +

    Here's where you discuss the abstractions +used by your package, such as the procedures encapsulating the legal +transactions on the data model. Explain the organization of +procedures and their particulars (detail above and beyond what is +documented in the code), including:

    + + + +

    Remember that the correctness, completeness, and stability of the +API and interface are what experienced members of our audience are +looking for. This is a cultural shift for us at aD (as of mid-year +2000), in that we've previously always looked at the data models as +key, and seldom spent much effort on the API (e.g. putting raw SQL in +pages to handle transactions, instead of encapsulating them via +procedures). Experience has taught us that we need to focus on the +API for maintainability of our systems in the face of constant +change.

    + +

    Also noteworthy is that although the OpenACS currently utilizes the +AOLserver Tcl API, the current drive towards Java is likely to effect +a change in the content of these sections in the future.

    + + +

    Data Model Discussion

    + +

    The data model discussion should do more than +merely display the SQL code, since this information is already be +available via a link in the "essentials" section above. +Instead, there should be a high-level discussion of how your data +model meets your solution requirements: why the database entities were +defined as they are, and what transactions you expect to occur. (There +may be some overlap with the API section.) Here are some starting +points:

    + +
    + + +

    User Interface

    + +

    In this section, discuss user interface +issues and pages to be built; can organize by the expected classes of +users. These may include:

    + + + +

    You may want to include page mockups, site-maps, or other visual +aids. Ideally this section is informed by some prototyping you've +done, to establish the package's usability with the client and other +interested parties.

    + +

    Note: In order that developer documentation be uniform across +different system documents, these users should herein be designated as +"the developer," "the OpenACS-admin," "the +sub-admin," and "the user," respectively.

    + +

    Finally, note that as our templating system becomes more entrenched +within the OpenACS, this section's details are likely to shift from UI +specifics to template interface specifics.

    + + +

    Configuration/Parameters

    + +

    Under OpenACS 4, parameters are set at two +levels: at the global level by the OpenACS-admin, and at the subsite +level by a sub-admin. In this section, list and discuss both levels +of parameters.

    + + +

    Future Improvements/Areas ofLikely Change

    + +

    If the system presently lacks +useful/desirable features, note details here. You could also comment +on non-functional improvements to the package, such as usability.

    + +

    Note that a careful treatment of the earlier "competitive +analysis" section can greatly facilitate the documenting of this +section.

    + + +

    Authors

    + +

    Although a system's data model file often +contains this information, this isn't always the case. Furthermore, +data model files often undergo substantial revision, making it +difficult to track down the system creator. An additional +complication: package documentation may be authored by people not +directly involved in coding. Thus to avoid unnecessary confusion, +include email links to the following roles as they may apply:

    + +
    + + +

    Revision History

    + + + + + + + + + + + +
    Document Revision #Action Taken, NotesWhen?By Whom?
    +

    ($Id: design.html,v 1.1 2005/08/31 17:05:18 leed Exp $)

    + + + Index: openacs-4/packages/image-magick/www/doc/index.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/www/doc/index.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/www/doc/index.html 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,26 @@ + + + + + + Package Documentation Index Template + + + + + + + + + + +

    Package Documentation Index Template

    + + + + + Index: openacs-4/packages/image-magick/www/doc/requirements.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/image-magick/www/doc/requirements.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/image-magick/www/doc/requirements.html 31 Aug 2005 17:05:18 -0000 1.1 @@ -0,0 +1,183 @@ + + + + + + Requirements Template + + + + + + + + + + + +

    System/Application Requirements Template

    + +

    By You

    + + +

    Introduction

    + +

    Briefly explain to the reader what this +document is for, whether it records the requirements for a new system, +a client application, a toolkit subsystem, etc. Remember your +audience: fellow programmers, AND interested non-technical parties +such as potential clients, who may all want to see how rigorous our +engineering process is. Here and everywhere, write clearly and +precisely; for requirements documentation, write at a level that any +intelligent layperson can understand.

    +
    + + +

    Vision Statement

    + +

    Very broadly, describe how the system meets a +need of a business, group, the OpenACS as a whole, etc. Make sure +that technical and non-technical readers alike would understand what +the system would do and why it's useful. Whenever applicable, you +should explicitly state what the business value of the system is.

    +
    + + +

    System/Application Overview

    + +

    Discuss the high-level breakdown of the +components that make up the system. You can go by functional areas, +by the main transactions the system allows, etc.

    + +

    You should also state the context and dependencies of the system +here, e.g. if it's an application-level package for OpenACS 4, briefly +describe how it uses kernel services, like permissions or +subsites.

    + +

    Use-cases and User-scenarios

    + +

    Determine the types or classes of users who +would use the system, and what their experience would be like at a +high-level. Sketch what their experience would be like and what +actions they would take, and how the system would support them.

    +
    + + +

    CompetitiveAnalysis (opt)

    + +

    Describe other systems or services that are +comparable to what you're building. If applicable, say why your +implementation will be superior, where it will match the competition, +and where/why it will lack existing best-of-breed capabilities. This +section is also in the Design doc, so write about it where you deem +most appropriate.

    +
    + +

    Related Links

    + +
    +

    Include all pertinent links to supporting and related material, + such as:

    + +
    + +

    Requirements

    + +

    The main course of the document, +requirements. Break up the requirements sections (A, B, C, etc.) as +needed. Within each section, create a list denominated with unique +identifiers that reflect any functional hierarchy present, +e.g. 20.5.13. - for the first number, leave generous gaps on the first +writing of requirements (e.g. 1, 10, 20, 30, 40, etc.) because you'll +want to leave room for any missing key requirements that may +arise.

    + + + +

    For guidelines writing requirements, take a look at the quality standards, along with a good +example, such as OpenACS 4 Package +Manager Requirements.

    + +

    Besides writing requirements in natural language, consider using +the following techniques as needed:

    + + +
    + + +

    Optional: Implementation Notes

    + +

    Although in theory coding comes after design, +which comes after requirements, we do not, and perhaps should not, +always follow such a rigid process (a.k.a. the waterfall lifecyle). +Often, there is a pre-existing system or prototype first, and thus you +may want to write some thoughts on implementation, for aiding and +guiding yourself or other programmers.

    +
    + +

    Revision History

    + + + + + + + + + + + +
    Document Revision #Action Taken, NotesWhen?By Whom?
    + +

    ($Id: requirements.html,v 1.1 2005/08/31 17:05:18 leed Exp $)

    + + +