<?xml version="1.0" encoding="UTF-8"?><rss xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns:p="http://outerx.org/daisy/1.0#publisher" xmlns:d="http://outerx.org/daisy/1.0" version="2.0"><channel><title>Wiki</title><link>http://cocoondev.org/wiki</link><description>A wiki for Daisy users.</description><item><title>New document browser</title><link>http://cocoondev.org/wiki/614-cd</link><description>&lt;html&gt;
&lt;head&gt;
&lt;META http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;base href="http://cocoondev.org"&gt;
&lt;link href="/resources/skins/default/css/daisy.css" type="text/css" rel="stylesheet"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1 xmlns:d="http://outerx.org/daisy/1.0" xmlns:lt="http://outerx.org/daisy/1.0#linktransformer" xmlns:einclude="http://outerx.org/daisy/1.0#externalinclude" xmlns:p="http://outerx.org/daisy/1.0#publisher" xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns:urlencoder="xalan://java.net.URLEncoder" id="dsy614-cd" class="daisy-document-name"&gt;New document browser&lt;/h1&gt;


&lt;h2 xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" xmlns:ns="http://outerx.org/daisy/1.0"&gt;Concept&lt;/h2&gt;


&lt;p&gt;A rewrite(?) of the existing document browser with some new features:&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;chunking&lt;/li&gt;

&lt;li&gt;sorting&lt;/li&gt;

&lt;li&gt;more search possiblities:&lt;/li&gt;

&lt;ul&gt;

&lt;li&gt;facet browsing&lt;/li&gt;

&lt;li&gt;predefined filters&lt;/li&gt;

&lt;/ul&gt;


&lt;li&gt;lookup of related WFs and possible transitions in the various tasks (?)&lt;/li&gt;

&lt;li&gt;multi-document-selection (useful for making multi-value daisy-link field
editors friendlier)&lt;/li&gt;

&lt;li&gt;pdf export&lt;/li&gt;

&lt;ul&gt;

&lt;li&gt;some standard listing of the current resultset to pdf&lt;/li&gt;

&lt;li&gt;bonus for having a pluggable xsl-fo of some sort (pulling in logos and stuff
&lt;/li&gt;

&lt;/ul&gt;


&lt;li&gt;extra actions:&lt;/li&gt;

&lt;ul&gt;

&lt;li&gt;in the search-result list, there could be buttons to various actions.&amp;nbsp; These
could be general actions (like "show", "edit", "start workflow"...) or
user-defined actions (i.e.
/daisy/site/ext/some-custom-action?documentId={docId})&lt;/li&gt;

&lt;/ul&gt;


&lt;/ul&gt;


&lt;p&gt;There are several places where the document browser could be used, with
different configuration requirements (e.g. when linking to a document,
multi-selection would not make sense).&amp;nbsp; Hence, there would be an xml document
that configures the document browser instance, a query parameter can then be
used&lt;br&gt;
to select the right configuration:&lt;br&gt;
http://.../daisy/site/documentBrowser?config=images&lt;br&gt;
would match ${wikidata}/conf/documentbrowser-{config}.xml&lt;/p&gt;


&lt;pre&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;docbrowser&amp;gt;
  &amp;lt;aspects&amp;gt;
    &amp;lt;daisy-meta/&amp;gt;
    &amp;lt;fulltext/&amp;gt;
    &amp;lt;facets&amp;gt;
      &amp;lt;!-- ... configuration for facets --&amp;gt;
    &amp;lt;predefined&amp;gt;
      &amp;lt;predef label="predef.withnavpart"&amp;gt;hasPart("NavigationData")&amp;lt;/predef&amp;gt;
      &amp;lt;predef label="predef.summercollection"&amp;gt;InCollection("summer")&amp;lt;/predef&amp;gt;
      ...
    &amp;lt;/predefined&amp;gt;
  &amp;lt;/aspects&amp;gt;

  &amp;lt;results multiselect="true"&amp;gt;
    &amp;lt;columns&amp;gt;
      &amp;lt;column label="docbrowser.id" select="id"/&amp;gt;
      &amp;lt;column label="docbrowser.name" select="name"/&amp;gt;
      &amp;lt;column label="docbrowser.lastModifierLogin" select="lastModifierLogin"/&amp;gt;
      &amp;lt;column label="docbrowser.lastModified" select="lastModified"/&amp;gt;
      &amp;lt;column label="docbrowser.pubYear" select="Year(Publication)"/&amp;gt;
      &amp;lt;column label="docbrowser.somethingelse" select="Random()"/&amp;gt;
      &amp;lt;column label="docbrowser.aMultiValueField" select="$Gimmicks"/&amp;gt;
      &amp;lt;!-- NTH: this may be a good place to say something about date formatting as well --&amp;gt;
    &amp;lt;/columns&amp;gt;
    &amp;lt;row-actions&amp;gt;
      &amp;lt;builtin-action label="showPreview" type="showPreview"/&amp;gt;
      &amp;lt;custom-action label="startWorkflow" url="{pageContext.mountPoint}/{site}/workflow/new?documentId={row.id}" icon="{pageContext.mountPoitn}/resources/skins/{skin}/img/wf.png"/&amp;gt;
      &amp;lt;custom-action label="mailTo" url="mailto:user@example.com?subject=Daisy Document: {row.name}&amp;amp;body=Click here for to for an interesting document: {pageContext.baseurl}/{pageContext.mountPoint}/{site}/workflow/new?documentId={row.id}" icon="{pageContext...}/email.png"/&amp;gt;
      &amp;lt;custom-action label="showReferrers" url="{pageContext.mountPoint}/{site}/{row.id}/referrers.html" icon="{...}/refer.png"/&amp;gt;
    &amp;lt;/row-actions&amp;gt;
    &amp;lt;actions&amp;gt;
      &amp;lt;custom-action label="exportPdf" url=".../exportPdf?ids={comma_separated_ids}"/&amp;gt;  &amp;lt;!-- Probably needs to support POST-links to be practical, plus ways to control what is sent. --&amp;gt;
    &amp;lt;/actions&amp;gt;
  &amp;lt;/results&amp;gt;
&amp;lt;/docbrowser&amp;gt;&lt;/pre&gt;


&lt;h2&gt;Layout ideas&lt;/h2&gt;


&lt;p&gt;Like the current document browser, the document browser would have two
distinct halves: The "search" part and the "search-result" part.&lt;br&gt;
The "search" part would show different search aspects: fulltext, daisy-metadata,
facets and predefined filters.&lt;br&gt;
To save space, these would be rendered in tabs or an accordeon widget.&lt;/p&gt;


&lt;p&gt;The "search-result" part would become table-like (like the querySearch
results), but there should be a possibility of toggling between "table" mode and
"preview mode" (preview-mode being the style used in the current document
browser).&lt;/p&gt;


&lt;h2&gt;Mockups&lt;/h2&gt;


&lt;p&gt;These are the 'search' aspects as they would appear in an accordeon widget
(all aspects are shown in collapsed mode and in expanded mode)&lt;/p&gt;


&lt;p&gt;
&lt;img alt="docbrowser search aspects" title="docbrowser search aspects" src="/wiki/618-cd/version/default/part/ImageData/data/search-aspects.png"&gt;&lt;/p&gt;


&lt;p&gt;This is what the whole document browser would look like:&lt;/p&gt;


&lt;p&gt;
&lt;table class="plainTable"&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a style="border: 1px" href="/wiki/619-cd/version/default/part/ImageData/data/docbrowser-mockup.png"&gt;&lt;img alt="docbrowser-mockup" title="docbrowser-mockup" src="/wiki/619-cd/version/default/part/ImagePreview/data"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;a style="font-style: italic" href="/wiki/619-cd/version/default/part/ImageData/data/docbrowser-mockup.png"&gt;Click to enlarge&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/p&gt;


&lt;h3&gt;Additional requirements (not visible in current mockups):&lt;/h3&gt;


&lt;ul&gt;

&lt;li&gt;A button to toggle between "preview" and "table" mode.&lt;/li&gt;

&lt;li&gt;Chunking links&lt;/li&gt;

&lt;li&gt;A button to toggle between "results" and "current selection" (the current
selection of documents must be available even if not all documents are in the
current resultset.&lt;/li&gt;

&lt;/ul&gt;


&lt;/body&gt;
&lt;/html&gt;
</description></item><item xmlns:s="http://outerx.org/daisywiki/1.0#serializer"><title>Creating a multi role authentication scheme</title><link>http://cocoondev.org/wiki/620-cd</link><description>&lt;html&gt;
&lt;head&gt;
&lt;META http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;base href="http://cocoondev.org"&gt;
&lt;link href="/resources/skins/default/css/daisy.css" type="text/css" rel="stylesheet"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1 xmlns:d="http://outerx.org/daisy/1.0" xmlns:lt="http://outerx.org/daisy/1.0#linktransformer" xmlns:einclude="http://outerx.org/daisy/1.0#externalinclude" xmlns:p="http://outerx.org/daisy/1.0#publisher" xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns:urlencoder="xalan://java.net.URLEncoder" id="dsy620-cd" class="daisy-document-name"&gt;Creating a multi role authentication scheme&lt;/h1&gt;


&lt;p xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" xmlns:ns="http://outerx.org/daisy/1.0"&gt;This step by step instruction explains how to extend the Daisy CMS with your
own authentication scheme that fits your needs.&lt;/p&gt;


&lt;p&gt;
&lt;strong&gt;Assumption&lt;/strong&gt;: You already set up daisy on a windows system and
everything's working great. Your also doing the codeing and compiling on a
separate system (a mac) because you too lazy to install the dev tool on the
windows sever...&lt;/p&gt;


&lt;p&gt;
&lt;strong&gt;Task&lt;/strong&gt;: You would like new daisy users to be allocated a given
role when they first logon. The system admin chaps would ideally like the group
the user belongs to on a windows network to dictate this role allocation.&lt;/p&gt;


&lt;p class="note"&gt;This solution is useful where there are a number of different
users who need to see different resources on the same server (ie. student and
staff at a university).&lt;/p&gt;


&lt;h2&gt;Step 1: Checking out the sources&lt;/h2&gt;


&lt;p&gt;Download the daisy sources daisy-x.x.x.tar.gz of the latest stable (or
milestone) release at the
&lt;a href="http://svn.cocoondev.org/dist/daisy/"&gt;download area&lt;/a&gt; (or
&lt;a href="http://cocoondev.org/daisydocs-1_3/152.html"&gt;check out&lt;/a&gt; the lastest
version from SVN, whatever you prefer). Extract the tarball into a directory on
your local machine (although you do not have to create that environment
variable, I will refer to that directory as DAISY_SRC during the rest ot this
tutorial):&lt;/p&gt;


&lt;pre&gt;$ tar xvzf daisy-x.x.x.tar.gz&lt;/pre&gt;


&lt;h2&gt;Step 2: Copy the sources of the Ntlm-authentication&lt;/h2&gt;


&lt;p&gt;Descend to the dircectory $DAISY_SRC/services/ and make a copy of the
directory ntlm-auth, which contains the sources for the Ntlm authentication
scheme. We take these sources as starting point and we will modify them to fit
our needs.&lt;/p&gt;


&lt;pre&gt;$ cp -R ntlm-auth/ ntlm-group-auth&lt;/pre&gt;


&lt;h2&gt;Step 3: Create the java classes for authentication&lt;/h2&gt;


&lt;h3&gt;Step 3a: Rename the existing sourcefiles for AuthenticationFactory and
AuthenticationScheme&lt;/h3&gt;


&lt;p&gt;Descend into the directory
$DAISY_SRC/services/ssh-auth/src/java/org/outerj/daisy/authentication/impl&lt;br&gt;
Rename the both existing sourcefiles for the AuthenticationFactory and the
AuthenticationScheme&lt;/p&gt;


&lt;pre&gt;$ mv NtlmAuthenticationFactory.java NtlmGroupAuthenticationFactory.java
$ mv NtlmAuthenticationScheme.java NtlmGroupAuthenticationScheme.java&lt;/pre&gt;


&lt;h3&gt;Step 3b: Edit NTLMGroupAuthenticationFactory.java&lt;/h3&gt;


&lt;p&gt;In your favourite editor or IDE, edit the source file for the NTLM Group
Authentication Factory and change it to:&lt;/p&gt;


&lt;pre&gt;package org.outerj.daisy.authentication.impl;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.outerj.daisy.authentication.spi.*;
import org.outerj.daisy.plugin.PluginRegistry;

import javax.annotation.PreDestroy;
import java.util.Map;
import java.util.HashMap;

/**
 * Constructs and registers NtlmGroupAuthenticationSchemes with the UserAuthenticator.
 *
 */
public class NtlmGroupAuthenticationFactory  {
    private PluginRegistry pluginRegistry;
    private Map&amp;lt;String, AuthenticationScheme&amp;gt; schemes = new HashMap&amp;lt;String, AuthenticationScheme&amp;gt;();

    public NtlmGroupAuthenticationFactory(Configuration configuration, PluginRegistry pluginRegistry) throws Exception {
        this.pluginRegistry = pluginRegistry;
        this.configure(configuration);
        registerSchemes();
    }

    @PreDestroy
    public void destroy() {
        unregisterSchemes();
    }

    private void registerSchemes() throws Exception {
        for (Map.Entry&amp;lt;String, AuthenticationScheme&amp;gt; entry : schemes.entrySet()) {
            pluginRegistry.addPlugin(AuthenticationScheme.class, entry.getKey(), entry.getValue());
        }
    }

    private void unregisterSchemes() {
        for (Map.Entry&amp;lt;String, AuthenticationScheme&amp;gt; entry : schemes.entrySet()) {
            pluginRegistry.removePlugin(AuthenticationScheme.class, entry.getKey(), entry.getValue());
        }
    }

    private void configure(Configuration configuration) throws ConfigurationException {
        Configuration[] schemeConfs = configuration.getChildren("scheme");
        for (Configuration schemeConf : schemeConfs) {
            String name = schemeConf.getAttribute("name");
            String description = schemeConf.getAttribute("description");
            String domainControllerAddress = schemeConf.getChild("domainControllerAddress").getValue();
            String domain = schemeConf.getChild("domain").getValue();
			
			String file1 = schemeConf.getChild("fileLocation1").getValue();
			String file2 = schemeConf.getChild("fileLocation2").getValue();
			
			Configuration subUserCreator1 = schemeConf.getChild("subUserCreator1");
			UserCreator userCreator1 = UserCreatorFactory.createUser(subUserCreator1, name);
			
			
			Configuration subUserCreator2 = schemeConf.getChild("subUserCreator2");			
			UserCreator userCreator2 = UserCreatorFactory.createUser(subUserCreator2, name);

		
			AuthenticationScheme scheme = new NtlmGroupAuthenticationScheme(name, description, domainControllerAddress, domain, file1, userCreator1, file2, userCreator2);
			Configuration cacheConf = schemeConf.getChild("cache");
			if (cacheConf.getAttributeAsBoolean("enabled")) {
				int maxCacheSize = cacheConf.getAttributeAsInteger("maxCacheSize", 3000);
				long maxCacheDuration = cacheConf.getAttributeAsLong("maxCacheDuration", 30 * 60 * 1000); // default: half an hour
				scheme = new CachingAuthenticationScheme(scheme, maxCacheDuration, maxCacheSize);
			}

			if (schemes.containsKey(name))
				throw new ConfigurationException("Duplicate authentication scheme name: " + name);
			
			schemes.put(name, scheme);
				

            
        }
    }
}&lt;/pre&gt;


&lt;p&gt;Note that this authentication factory reads in the configuration for two
files and userCreators which are then passed to the authentication scheme.&lt;/p&gt;


&lt;h3&gt;Step 3c: Edit NTLMGroupAuthenticationScheme.java&lt;/h3&gt;


&lt;p&gt;In your favourite editor or IDE, edit the source file for the NTLM Group
Authentication Scheme and change it to:&lt;/p&gt;


&lt;pre&gt;package org.outerj.daisy.authentication.impl;

import org.outerj.daisy.authentication.spi.AuthenticationScheme;
import org.outerj.daisy.authentication.spi.AuthenticationException;
import org.outerj.daisy.authentication.spi.UserCreator;
import org.outerj.daisy.repository.Credentials;
import org.outerj.daisy.repository.user.User;
import org.outerj.daisy.repository.user.UserManager;
import jcifs.smb.SmbException;
import jcifs.smb.SmbAuthException;
import jcifs.smb.SmbSession;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.*;
import jcifs.UniAddress;

import java.net.UnknownHostException;
import java.net.MalformedURLException;

public class NtlmGroupAuthenticationScheme implements AuthenticationScheme {
    private final String name;
    private final String description;
    private final String domainControllerAddress;
    private final String domain;
	private final String file1;
    private final UserCreator userCreator1;
	private final String file2;
    private final UserCreator userCreator2;

    public NtlmGroupAuthenticationScheme(String name, String description, String domainControllerAddress, String domain, String file1, UserCreator userCreator1, String file2, UserCreator userCreator2) {
        this.name = name;
        this.description = description;
        this.domainControllerAddress = domainControllerAddress;
        this.domain = domain;
		this.file1 = file1;
		this.userCreator1 = userCreator1;
		this.file2 = file2;
        this.userCreator2 = userCreator2;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public boolean check(Credentials credentials) throws AuthenticationException {
		if ( check1(credentials) ) {
			return true;
		}
		if ( check2(credentials) ) {
			return true;
		}			
		return false;
    }

    public boolean check1(Credentials credentials) throws AuthenticationException {
        UniAddress mydomaincontroller;
        try {
            mydomaincontroller = UniAddress.getByName(domainControllerAddress);
        } catch (UnknownHostException e) {
            throw new AuthenticationException("Error authenticating using NTLM.", e);
        }
        NtlmPasswordAuthentication mycreds = new NtlmPasswordAuthentication(domain, credentials.getLogin(), credentials.getPassword());		
		jcifs.Config.registerSmbURLHandler();
		SmbFile smbf;
		try {
			smbf = new SmbFile(file1, mycreds);

		}	catch( MalformedURLException seed ) {
            // NETWORK PROBLEMS?
            throw new AuthenticationException("Can't find the file specified", seed);
        }

        try {			
            return smbf.exists();	
        } catch( SmbAuthException sae ) {
            // AUTHENTICATION FAILURE
            return false;
        } catch( SmbException se ) {
            // NETWORK PROBLEMS?
            throw new AuthenticationException("Error authenticating using NTLM.", se);
        }
    }

    public boolean check2(Credentials credentials) throws AuthenticationException {
        UniAddress mydomaincontroller;
        try {
            mydomaincontroller = UniAddress.getByName(domainControllerAddress);
        } catch (UnknownHostException e) {
            throw new AuthenticationException("Error authenticating using NTLM.", e);
        }
        NtlmPasswordAuthentication mycreds = new NtlmPasswordAuthentication(domain, credentials.getLogin(), credentials.getPassword());
		
		jcifs.Config.registerSmbURLHandler();
		
		SmbFile smbf;
		
		try {
			smbf = new SmbFile(file2, mycreds);
		}	catch( MalformedURLException seed ) {
            // NETWORK PROBLEMS?
            throw new AuthenticationException("Can't find the file specified", seed);
        }

        try {
									
			return smbf.exists();
			
        } catch( SmbAuthException sae ) {
            // AUTHENTICATION FAILURE
            return false;
        } catch( SmbException se ) {
            // NETWORK PROBLEMS?
            throw new AuthenticationException("Error authenticating using NTLM.", se);
        }
    }

    public void clearCaches() {
        // do nothing
    }

    public User createUser(Credentials crendentials, UserManager userManager) throws AuthenticationException {
        if (userCreator1 != null) {
		if (check1(crendentials)) {
				User aUser = userCreator1.create(crendentials.getLogin(), userManager);
				return aUser;				
			}
        }
		if (userCreator2 != null) {
			if (check2(crendentials)) {
				User aUser = userCreator2.create(crendentials.getLogin(), userManager);
				return aUser;					
			}
        }
        return null;
    }
}

&lt;/pre&gt;


&lt;p&gt;The jcifs library which daisy uses to perform NTLM authentication does not
provide a simple method for checking if a user belongs to a certain windows
group. However, by using the SmbFile() method for the jcifs library we can see
if a user with a siven set of creidentials can access a file on a windows share.
As a windows server can restrict access using groups this provides a cunning
workaround.&lt;/p&gt;


&lt;p&gt;The location of the file and other parameters are read from a the
configuration file myconfig.xml, which we will create later on. This information
is used inside the constructor of a new instance of our SSHAuthenticationScheme,
which we created above.&lt;/p&gt;


&lt;p&gt;You'll notice this section of code contains a number of fairly similar
methods [i.e. check1() and check2()]. The methods which Daisy itself uses&amp;nbsp; [i.e.
check() and createUser()] calls these in order to perform the authentication at
the two different levels .&lt;/p&gt;


&lt;p class="note"&gt;I'm sure there a more elegent way of doing this....&lt;/p&gt;


&lt;h2&gt;Step 4: Building the authentication scheme&lt;/h2&gt;


&lt;h3&gt;Step 4a: Compiling and packing your classes&lt;/h3&gt;


&lt;p&gt;I compile the files on my mac something like this:&lt;/p&gt;


&lt;p class="note"&gt;Use the method of your choice to compile the code (Ant, Maven,
your IDE, ...). When using the command below, we hope you know enough about this
that everything should be on one line. For Windows, replace $DAISY_HOME with
%DAISY_HOME% and the colons with semicolons)&lt;/p&gt;


&lt;pre&gt;javac -classpath 
   ~/Documents/intranet/daisy-2.2/lib/daisy/jars/daisy-repository-api-2.2.jar:
   ~/Documents/intranet/daisy-2.2/lib/daisy/jars/daisy-repository-server-spi-2.2.jar:
   ~/Documents/intranet/daisy-2.2/lib/daisy/jars/daisy-pluginregistry-api-2.2.jar:
   ~/Documents/intranet/daisy-2.2/lib/daisy/jars/daisy-pluginregistry-api-2.2.jar:
   ~/Documents/intranet/daisy-2.2/lib/avalon-framework/jars/avalon-framework-api-4.3.jar:
   ~/Documents/intranet/daisy-2.2/lib/jcifs/jars/jcifs-1.1.11.jar:
   ~/Documents/intranet/daisy-2.2/lib/javax.annotation/jars/jsr250-api-1.0.jar:
   ~/Documents/intranet/daisy-2.2/lib/javax.servlet/jars/servlet-api-2.4.jar:
   ~/Documents/intranet/ntlm-group-auth/src/org/outerj/daisy/authentication/impl/NtlmGroupAuthenticationScheme.class 
   ~/Documents/intranet/ntlm-group-auth/src/org/outerj/daisy/authentication/impl/NtlmGroupAuthenticationFactory.java 
   ~/Documents/intranet/ntlm-group-auth/src/org/outerj/daisy/authentication/impl/NtlmGroupAuthenticationScheme.java

jar cvf ntlm-group-auth.jar *&lt;/pre&gt;


&lt;p&gt;I run this command from the directory shown below:&lt;/p&gt;


&lt;pre&gt;~/Documents/intranet/ntlm-group-auth/src/&lt;/pre&gt;


&lt;h3&gt;Step 4b: Copying the jar-file into place&lt;/h3&gt;


&lt;p&gt;Copy the newly created jar file both into the lib directory of your daisy
binary distribution ($DAISY_HOME/lib). Copy the file
daisy-auth-ssh-&amp;lt;version&amp;gt;.jar into the directory daisy/jars/.&lt;/p&gt;


&lt;pre&gt;$ cp target/daisy-auth-ssh-&amp;lt;version&amp;gt;.jar $DAISY_HOME/lib/daisy/jars/&lt;/pre&gt;


&lt;p class="note"&gt;If you don't want to create a binary distribution of daisy it
might be sufficient to copy the jar-file to the $DAISY_HOME/lib directory only.
&lt;/p&gt;


&lt;p class="warn"&gt;Details from this point on are a little sketchy, need to check
the info on a different PC.&lt;/p&gt;


&lt;h2&gt;Step 5: Registering and configuring the new component&lt;/h2&gt;


&lt;h3&gt;Step 5a: Registering the new component&lt;/h3&gt;


&lt;p&gt;Edit the file $DAISY_HOME/repository-server/conf/block.xml. Inside the
container named authentication, include your newly created scheme. The element
&amp;lt;container&amp;gt; of block.xml now should look like (adapt the versions of your
jar files for ntlm and ssh authentication!):&lt;/p&gt;


&lt;pre&gt;&amp;lt;container name="authentication"&amp;gt;
  &amp;lt;services&amp;gt;
    &amp;lt;service type="org.outerj.daisy.authentication.UserAuthenticator"&amp;gt;
      &amp;lt;source&amp;gt;authenticator&amp;lt;/source&amp;gt;
    &amp;lt;/service&amp;gt;
    &amp;lt;service type="org.outerj.daisy.authentication.AuthenticationSchemeRegistrar"&amp;gt;
      &amp;lt;source&amp;gt;authenticator&amp;lt;/source&amp;gt;
    &amp;lt;/service&amp;gt;
  &amp;lt;/services&amp;gt;

  &amp;lt;component name="authenticator" class="org.outerj.daisy.authentication.impl.UserAuthenticatorImpl"/&amp;gt;

  &amp;lt;component name="daisy-native" class="org.outerj.daisy.authentication.impl.DaisyAuthenticationFactory"&amp;gt;
    &amp;lt;configuration&amp;gt;
      &amp;lt;cache enabled="true" maxCacheSize="3000" maxCacheDuration="1800000"/&amp;gt;
    &amp;lt;/configuration&amp;gt;
  &amp;lt;/component&amp;gt;

  &amp;lt;component name="ldap" class="org.outerj.daisy.authentication.impl.LdapAuthenticationFactory"&amp;gt;
    &amp;lt;configuration&amp;gt;
      &amp;lt;!-- See myconfig.xml.template for an example configuration --&amp;gt;
    &amp;lt;/configuration&amp;gt;
  &amp;lt;/component&amp;gt;

  &amp;lt;include name="ntlm" id="daisy:daisy-auth-ntlm" version="1.4-dev"/&amp;gt;
  &amp;lt;include name="ssh" id="daisy:daisy-auth-ssh" version="1.4-dev"/&amp;gt;
  &amp;lt;include name="ntlm-group" id="daisy:daisy-auth-ssh" version="1.4-dev"/&amp;gt;

&amp;lt;/container&amp;gt;&lt;/pre&gt;


&lt;h3&gt;Step 5b: Configuring the new component&lt;/h3&gt;


&lt;p&gt;Inside the directory $DAISY_HOME/repository-server/conf/ you will find a file
myconfig.xml.template. Copy this file into the directory conf/ inside your
repository and rename it to myconfig.xml&lt;/p&gt;


&lt;pre&gt;$ cp $DAISY_HOME/repository-server/conf/myconfig.xml.template /path/to/your/repository/conf/myconfig.xml&lt;/pre&gt;


&lt;p&gt;Edit the newly created file myconfig.xml. Add a target in order to configure
your authentication scheme, inside that target, fill in the IP or host name of
your SSH-server. Also, in order to enable automatically creation of user
accounts once the user logs in to daisy for the first time, define our newly
created scheme as authentification scheme for user creation as shown below:&lt;/p&gt;


&lt;pre&gt;&amp;lt;targets&amp;gt;
  &amp;lt;target path="..."
    ...
  &amp;lt;/target&amp;gt;

  ... many more targets

  &amp;lt;target path="/daisy/repository/authentication/authenticator"&amp;gt;
    &amp;lt;configuration&amp;gt;
      &amp;lt;!-- Indicates which authentication scheme to use, if any, to automatically create new users. --&amp;gt;
      &amp;lt;authenticationSchemeForUserCreation&amp;gt;ntlmgroup1&amp;lt;/authenticationSchemeForUserCreation&amp;gt;
    &amp;lt;/configuration&amp;gt;
  &amp;lt;/target&amp;gt;

  ... many more targets

  &amp;lt;target path="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"&amp;gt;
    &amp;lt;configuration&amp;gt;
       &amp;lt;!-- You can configure one or more NTLM-based authentication schemes here --&amp;gt;
          &amp;lt;!-- Notes:
                - the name of a scheme should not be daisy, no two schemes can have the same name
                - the autoCreateUser element is optional
          --&amp;gt;
          &amp;lt;scheme name="ntlmgroup1" description="Test NTLM Group config"&amp;gt;
            &amp;lt;domainControllerAddress&amp;gt;127.0.0.1&amp;lt;/domainControllerAddress&amp;gt;
            &amp;lt;domain&amp;gt;yum&amp;lt;/domain&amp;gt;
            &amp;lt;cache enabled="true" maxCacheSize="3000" maxCacheDuration="1800000"/&amp;gt;
			&amp;lt;fileLocation1&amp;gt;afilelocation&amp;lt;/fileLocation1&amp;gt;
			&amp;lt;fileLocation2&amp;gt;afilelocation&amp;lt;/fileLocation2&amp;gt;
			&amp;lt;subUserCreator1&amp;gt;
			   &amp;lt;autoCreateUser&amp;gt;
				  &amp;lt;roles&amp;gt;
					&amp;lt;role&amp;gt;User&amp;lt;/role&amp;gt;
				  &amp;lt;/roles&amp;gt;
				  &amp;lt;defaultRole&amp;gt;User&amp;lt;/defaultRole&amp;gt;
				  &amp;lt;updateableByUser&amp;gt;true&amp;lt;/updateableByUser&amp;gt;
				&amp;lt;/autoCreateUser&amp;gt;
				&amp;lt;test&amp;gt;astring&amp;lt;/test&amp;gt;
                         &amp;lt;/subUserCreator1&amp;gt;
			 &amp;lt;subUserCreator2&amp;gt;
			   &amp;lt;autoCreateUser&amp;gt;
				  &amp;lt;roles&amp;gt;
					&amp;lt;role&amp;gt;User&amp;lt;/role&amp;gt;
				  &amp;lt;/roles&amp;gt;
				  &amp;lt;defaultRole&amp;gt;User&amp;lt;/defaultRole&amp;gt;
				  &amp;lt;updateableByUser&amp;gt;true&amp;lt;/updateableByUser&amp;gt;
				&amp;lt;/autoCreateUser&amp;gt;
                         &amp;lt;/subUserCreator2&amp;gt;
	&amp;lt;/scheme&amp;gt;
    &amp;lt;/configuration&amp;gt;
  &amp;lt;/target&amp;gt;
&amp;lt;/targets&amp;gt;&lt;/pre&gt;


&lt;h2&gt;Step 6: Running and testing the new scheme&lt;/h2&gt;


&lt;p&gt;Now we are ready to test our new scheme! Restart the repository server and
the daisy wiki.&lt;br&gt;
Try to log on to daisy with any username/password combination which should have
permissions to access one of the files at either FileLocation1 or FileLocation2.
&lt;/p&gt;


&lt;p&gt;Log in should be successfull, you should be logged on with the role defined
in the myconfig.xml configuration file. Login as an administrator, invoke the
user administration. In the user list, an account should exist with the username
you just logged on as. Also, if you create a new user or edit an existing user,
in the drop-down box for the authentication scheme, you now should have the
choice between the daisy built in scheme and the scheme we newly created.&lt;/p&gt;


&lt;p&gt;It's worth noting a couple of points:&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;if a user can access both files at FileLocation1 and FileLocation2 they
don't get both sets of roles&lt;/li&gt;

&lt;li&gt;the roles associated with FileLocation1 and subUserCreator1 are checked
before&amp;nbsp; FileLocation2 and subUserCreator1&lt;/li&gt;

&lt;/ul&gt;


&lt;p&gt;Best of luck getting it to work. A working example is provided
&lt;a title="ntlm-group-auth" href="/wiki/621-cd/version/default/part/AttachmentData/data/ntlm-group-auth.jar"&gt;here&lt;/a&gt; (application/octet-stream, 11.4 kB, &lt;a href="/wiki/621-cd.html"&gt;info&lt;/a&gt;).&lt;/p&gt;


&lt;p class="warn"&gt;Java's not my strong point; I'd never coded in it before tying
this. I'm sure that there's a better way of structuring this code, possibly
involving passing arrays of FileLocations and subUserCreators from the
authentication factory to the authentication scheme. &lt;em&gt;Please leave some
hints. :)&lt;/em&gt;
&lt;/p&gt;


&lt;div class="doclinks"&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="mailto:andreas@deininger.net"&gt;Author: Andreas Deininger&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</description></item><item xmlns:s="http://outerx.org/daisywiki/1.0#serializer"><title>Display images in a query using query-styling</title><link>http://cocoondev.org/wiki/612-cd</link><description>&lt;html&gt;
&lt;head&gt;
&lt;META http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
&lt;base href="http://cocoondev.org"&gt;
&lt;link href="/resources/skins/default/css/daisy.css" type="text/css" rel="stylesheet"&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1 xmlns:d="http://outerx.org/daisy/1.0" xmlns:lt="http://outerx.org/daisy/1.0#linktransformer" xmlns:einclude="http://outerx.org/daisy/1.0#externalinclude" xmlns:p="http://outerx.org/daisy/1.0#publisher" xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns:urlencoder="xalan://java.net.URLEncoder" id="dsy612-cd" class="daisy-document-name"&gt;Display images in a query using query-styling&lt;/h1&gt;


&lt;h1 xmlns:jx="http://apache.org/cocoon/templates/jx/1.0" xmlns:ns="http://outerx.org/daisy/1.0"&gt;Objective&lt;/h1&gt;


&lt;p&gt;This article is about displaying a query-based table of images within a daisy
installation for the visual selection of pictures.&lt;/p&gt;


&lt;h1&gt;Background&lt;/h1&gt;


&lt;p&gt;Once daisy is accepted by those working with it (in our case a company using
it for background info and end-user documentation), a &lt;strong&gt;lot &lt;/strong&gt;of
pictures get uploaded ("a pictures makes up for a thousand words"). Even when
there are naming-conventions, the picture's names usually only make sense to
those who uploaded them.&lt;/p&gt;


&lt;p&gt;Since re-using a picture in several pages does not only make sense, but is
the only way for easing the exchange of e.g. a company logo easily across all
documents, we encountered the need to be able to query for all pictures in the
system including their thumbnail to have a visual choice of pictures..&lt;/p&gt;


&lt;p&gt;The problem is that pictures cannot be displayed within a query using a
standard daisy installation. Luckily the query may be "styled" manually.&lt;/p&gt;


&lt;p&gt;The following day-to-day notation is what this document aims to do:&lt;/p&gt;


&lt;pre&gt;select name, link, image_thumbnail from my_daisy&lt;/pre&gt;


&lt;p&gt;i.e. Select all names, links and the image thumbnail from a daisy
installation and display them as a table.&lt;/p&gt;


&lt;p class="note"&gt;
&lt;strong&gt;Credits&lt;/strong&gt;:&lt;br&gt;
Info, code and ideas for this document provided by J&amp;uacute;lio, Karel and Paul on
daisy's mailing list.&lt;/p&gt;


&lt;h1&gt;How it's done&lt;/h1&gt;


&lt;p&gt;Since daisy does not support querying for pictures, the trick is to add an
&lt;strong&gt;option &lt;/strong&gt;to the query with a &lt;strong&gt;style hint &lt;/strong&gt;that is
picked up by daisy and results in the display of the pictures rather than only
the name and link of the picture.&lt;/p&gt;


&lt;p&gt;Since daisy automatically generates a preview and a thumbnail from every
picture added to the system, one of these want to be displayed.&lt;/p&gt;


&lt;p&gt;The file handled is the one sitting in daisy's default template:&lt;/p&gt;


&lt;pre&gt;PATH_TO_DAISY/daisywiki/webapp/daisy/resources/skins/default/query-styling/query-styling-html.xsl &lt;/pre&gt;


&lt;p&gt;Copy this to your skin (create the folder, if not there):&lt;/p&gt;


&lt;pre&gt;PATH_TO_YOUR_SKIN/query-styling/&lt;/pre&gt;


&lt;p&gt;You will find the style-hint "bullets" already defined, we will add the the
two query styles&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;image-preview&lt;/li&gt;

&lt;li&gt;image-thumbnail&lt;/li&gt;

&lt;/ul&gt;


&lt;h1&gt;Adding the Code&lt;/h1&gt;


&lt;p&gt;Before you start adding the code, find out which partIDs your thumbnails and
previews have in you system.&lt;/p&gt;


&lt;h2&gt;Finding the Part Type of the Preview and the Thumbnail&lt;/h2&gt;


&lt;p&gt;You will need to hard-code the partIDs for your preview and thumbnail
pictures. Go to your &lt;em&gt;administration page&lt;/em&gt;, choose &lt;em&gt;Part Types&lt;/em&gt;
and note the IDs for the image preview and its thumbnail. In our case:&lt;/p&gt;


&lt;table class="default"&gt;
&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;

&lt;p&gt;12&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;ImagePreview&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;false&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;view/edit | delete&lt;/p&gt;

&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

&lt;p&gt;11&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;ImageThumbnail&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;false&lt;/p&gt;

&lt;/td&gt;
&lt;td&gt;

&lt;p&gt;view/edit | delete&lt;/p&gt;

&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;This should apply all systems that have not been tweeked.&lt;/p&gt;


&lt;h2&gt;Code to add to query-styling-html.xsl&lt;/h2&gt;


&lt;p&gt;J&amp;uacute;lio came up with the idea of using the same template for previews and
thumbnails (a bit smaller and faster to load than previews.)&lt;br&gt;
Therefore two templates are added that simply set some variables and then call
the template that sorts out the rest.&lt;br&gt;
This is it:&lt;/p&gt;


&lt;pre&gt;
&lt;strong&gt;&amp;lt;!--image-preview--&amp;gt;
&lt;/strong&gt;
&amp;lt;xsl:template match="d:searchResult[@styleHint='image-preview']"&amp;gt;
&amp;nbsp; &amp;lt;xsl:call-template name="tabular-results-with-image"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:with-param name="partId" select="12"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:with-param name="imageTitle" select="'Preview'"/&amp;gt;
&amp;nbsp; &amp;lt;/xsl:call-template&amp;gt;
&amp;lt;/xsl:template&amp;gt;


&lt;strong&gt;&amp;lt;!--image-thumbnail--&amp;gt;&lt;/strong&gt;
&amp;lt;xsl:template match="d:searchResult[@styleHint='image-thumbnail']"&amp;gt;
&amp;nbsp; &amp;lt;xsl:call-template name="tabular-results-with-image"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:with-param name="partId" select="11"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:with-param name="imageTitle" select="'Thumbnail'"/&amp;gt;
&amp;nbsp; &amp;lt;/xsl:call-template&amp;gt;
&amp;lt;/xsl:template&amp;gt;

&lt;strong&gt;&amp;lt;!--used by image-thumbnail and image-preview--&amp;gt;&lt;/strong&gt;
&amp;lt;xsl:template name="tabular-results-with-image"&amp;gt;
&amp;nbsp; &amp;lt;xsl:param name="partId"/&amp;gt;
  &amp;lt;xsl:param name="imageTitle"/&amp;gt;
&amp;nbsp; &amp;lt;table class="default"&amp;gt;
&lt;strong&gt; &amp;nbsp;&amp;nbsp; &amp;lt;!--table header--&amp;gt;
&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;tr&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;th&amp;gt;&amp;lt;xsl:value-of select="$imageTitle"/&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;xsl:for-each select="d:titles/d:title"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;th&amp;gt;&amp;lt;xsl:value-of select="."/&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;/xsl:for-each&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;th&amp;gt;&amp;lt;i18n:text key="searchresult.actions"/&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;/tr&amp;gt;

&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--table body--&amp;gt;&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:for-each select="d:rows/d:row"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;tr&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:variable name="hrefSuffix"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:if test="@branchId != $siteBranchId or @languageId !=$siteLanguageId"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:value-of select="concat('?branch=', @branchId, '&amp;amp;amp;language=', @languageId)"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xsl:if&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xsl:variable&amp;gt;
&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--image--&amp;gt;&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;td&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;img src="{@documentId}/version/last/part/{$partId}/data{$hrefSuffix}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/td&amp;gt;
&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--other fields--&amp;gt;&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:for-each select="d:value|d:xmlValue|d:multiValue|d:linkValue|d:hierarchyValue"&amp;gt; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;td&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;xsl:apply-templates select="."/&amp;gt; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/td&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xsl:for-each&amp;gt;
&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--action link--&amp;gt;&lt;/strong&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;td&amp;gt;&amp;lt;a href="{$searchResultBasePath}{@documentId}.html{$hrefSuffix}"&amp;gt;&amp;lt;i18n:text key="searchresult.action-show"/&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/tr&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/xsl:for-each&amp;gt;
&amp;nbsp; &amp;lt;/table&amp;gt;
&amp;lt;/xsl:template&amp;gt;&lt;/pre&gt;


&lt;p&gt;If you want to use the "i18n" tags, you will need to tell daisy what to do
with them, by adding the following code at the top section of the xsl file
(right under xmlns:d="http://outerx.org/daisy/1.0").&lt;/p&gt;


&lt;pre&gt;xmlns:i18n="http://apache.org/coccon/i18n/2.1"&lt;/pre&gt;


&lt;p&gt;If you want to change the order, eg. have the thumbnail at the end of the
table, you simply take the image part and put it at the end.&lt;/p&gt;


&lt;h2&gt;Making your changes visible to Daisy&lt;/h2&gt;


&lt;p&gt;Daisy won't automatically notice changes to documents inside the
&lt;tt&gt;&amp;lt;skin&amp;gt;/query-styling&lt;/tt&gt; directory, so one way of letting Daisy know
you've changed the query styling is:&lt;/p&gt;


&lt;ol&gt;

&lt;li&gt;Make sure you have a &lt;tt&gt;&amp;lt;skin&amp;gt;/searchresult.xsl&lt;/tt&gt; file. If you
haven't created one for your skin, copy the default &lt;tt&gt;searchresult.xsl&lt;/tt&gt;
file from &lt;tt&gt;daisy-&amp;lt;X.Y&amp;gt;/daisywiki/webapp/daisy/resources/xslt&lt;/tt&gt;
&lt;/li&gt;

&lt;li&gt;Change the &lt;tt&gt;searchresult.xsl&lt;/tt&gt; file. All you need is to change the
file's timestamp, and Daisy will pick up the changes to all files inside
/query-styling. You can type the command &lt;tt&gt;touch searchresult.xsl&lt;/tt&gt; in your
Daisy server's Un*x shell, or re-upload a local copy of
&lt;tt&gt;searchresult.xsl&lt;/tt&gt; via FTP.&lt;/li&gt;

&lt;/ol&gt;


&lt;p&gt;Remember to 'touch' &lt;tt&gt;searchresult.xsl&lt;/tt&gt; everytime you change the query
styling, or the changes won't be applied until the next time Daisy is reset.&lt;/p&gt;


&lt;h2&gt;Using style-hints&lt;/h2&gt;


&lt;p&gt;Once you have set up the file, you can start using the style-hints. Below are
two examples, each using one of the introduced style-hints.&lt;/p&gt;


&lt;pre&gt;select name, id, language where documentType='Image' and languageId = '2' order by name option style_hint = 'image-preview'&lt;/pre&gt;


&lt;pre&gt;select name, id where documentType='Image' and languageId = '3' order by id option style_hint = 'image-thumbnail'&lt;/pre&gt;


&lt;/body&gt;
&lt;/html&gt;
</description></item></channel></rss>