All pages of the documentation


Introduction

What is PmWiki?

PmWiki is a wiki-based system for collaborative creation and maintenance of websites. See PmWiki.

What can I do with it?

PmWiki pages look and act like normal web pages, except they have an "Edit" link that makes it easy to modify existing pages and add new pages into the website, using basic editing rules. You do not need to know or use any HTML or CSS. Page editing can be left open to the public or restricted to small groups of authors. Feel free to experiment with the Text Formatting Rules in the "Wiki sandbox". The website you're currently viewing is built and maintained with PmWiki.

What are the requirements?

See the PmWiki requirements page.

Where can I find documentation?

See the documentation index page.

How can I download PmWiki?

See the download page.

How do I install PmWiki?

Instructions for installation are on the installation page.

How do I get help with PmWiki?

See Mailing lists and How to get assistance.

How do you pronounce "Michaud"?

"Michaud" is french pronounced "mee show", the trailing D is silent.


Basic PmWiki editing rules

The pages on this site are wiki-based pages, which means that pages can be created and edited by multiple authors. To edit a page, click the Edit link that exists somewhere on the page, usually in the header or footer. Some pages may be password-protected, depending on the system's security policies, but many systems allow open editing of pages.

PmWiki is not WYSIWYG - When editing a page, you see the markup text that describes the content of the page. The basic rules for page markup are simple:

  1. Use a blank line to start a new paragraph more.
  2. To make a list, start each line with # for numbered (ordered) lists or * for bulleted (unordered) lists more.
  3. To make a heading, start a line with two or more ! marks; !! is a subheading, and !!! is a sub-subheading more.
  4. To emphasize text, enclose it in 2 or 3 single quotes; ''text'' for italics or '''text''' for bold more.
  5. To make a link to another page, enclose the page's name in double brackets; for example [[basic editing]] links to this page.
  6. To make a link to another site, type its address, such as [[http://example.com/]]. Email links must have "mailto:" before such as mailto:xyz@example.com -> mailto:xyz [snail] example [period] com

If you want to experiment with editing a page, try it on the Wiki Sandbox. You can edit the Wiki Sandbox without affecting anything important on this site. On talk pages and discussions, it's courteous to sign your contribution; using ~~~ effectively 'signs' the name that you provide in the Author field on the Page Edit form.

Examples of common markups

The tables below demonstrate many of the common markups used to format pages. The left column shows what to write to achieve the effect, the right column shows the effect of the markup. More details are available from the text formatting rules and other documentation pages. An exhaustive list of default markup is available as the markup master index.

Paragraphs and line breaks

What to type

What it looks like

Consecutive lines
will be merged together
as part of the same paragraph.

One or more empty lines will start a new paragraph.

Consecutive lines will be merged together as part of the same paragraph.

One or more empty lines will start a new paragraph.

Two backslashes at the end of a line \\
force a line break.

Or use this markup: [[<<]] to force a break.

Two backslashes at the end of a line
force a line break.

Or use this markup:
to force a break.

Further reading:

  • text formatting rules for more information on linebreaks, indented or hanging paragraphs.
  • wiki styles for centered or right justified paragraphs and "floating" text (boxes), borders and much more.

Lists

Start each line with # for numbered (ordered) lists or * for bulleted (unordered) lists:

* Bullet list
* Another item
** More asterisks produce sub-items
** etc.
  • Bullet list
  • Another item
    • More asterisks produce sub-items
    • etc.
# Numbered lists
# Another item
## more hashes produce sub-items
  1. Numbered lists
  2. Another item
    1. more hashes produce sub-items
# List types
# can be mixed
** numbered list with unordered sub-list
  1. List types
  2. can be mixed
    • numbered list with unordered sub-list

Learn more about lists (including definition lists) and list styles.

Headings

Headings are useful for creating a "well-structured" page. They're not just for making big text.

What to type

What it looks like

!! Major Subheading
!!! Minor Subheading
!!!! And More
!!!!! Subheadings

Major Subheading

Minor Subheading

And More

Subheadings

Text Emphasis

To emphasize, enclose text in apostrophes (single-quote marks), not double-quotes.

What to type

What it looks like

''Emphasize'' (italics),
'''strong''' (bold), 
'''''very strong''''' (bold italics).

Emphasize (italics), strong (bold), very strong (bold italics).

Links

To make a link to another page, enclose the page's name in double square brackets.

What to type

What it looks like

Practice editing in the [[wiki sandbox]]

Practice editing in the wiki sandbox

Note that words are automatically capitalized in page titles. The link above links to the page WikiSandbox.

Text after a pipe (|) is used as the link text:

Practice editing in the
[[WikiSandbox | practice area]].

Practice editing in the practice area.

Endings become part of the link text, parentheses hide parts of the link name:

[[wiki sandbox]]es.

[[(wiki) sandbox]].

wiki sandboxes.

sandbox.

When linking to a page in a different WikiGroup, provide the group name, followed by a separator, and then the page name:

[[Main.Wiki Sandbox]] shows group + name

[[Main/Wiki Sandbox]] shows only name

Main.Wiki Sandbox shows group + name

Wiki Sandbox shows only name

Links to external sites

bare url:  http://www.pmwiki.org

link text: [[http://www.pmwiki.org | PmWiki home]]

bare url: http://www.pmwiki.org

link text: PmWiki home

Links as reference to external sites

bare url: http://www.pmwiki.org

link text: [[http://www.pmwiki.org | #]]

bare url: http://www.pmwiki.org

link text: [1]

Colons make InterMap (also called InterWiki?) links to other wikis:

What's an [[Wikipedia:aardvark]], anyway?

What's an Wikipedia:aardvark, anyway?

Links to nonexistent pages? are displayed specially, to invite others to create the page.

PmWiki supports more link types and a lot of display options, see Links to learn more.

Preformatted text

Preformatted text is displayed using a monospace font and not generating linebreaks except where explicitly indicated in the markup.

Note that very long lines of preformatted text can cause the whole page to be wide.

For preformatted text with markup (e.g. emphasis) being processed, start each line with a space:

 Lines that begin with a space
 are formatted exactly as typed
 in a '''fixed-width''' font.
 Lines that begin with a space
 are formatted exactly as typed
 in a fixed-width font.

If you don't want Wiki markup to be processed, use [@ @]. Can also be used inline.

[@
Text escaped this way has
the HTML ''code'' style
@]
Text escaped this way has
the HTML ''code'' style

Escape sequence

If you don't want Wiki markup to be processed, but lines reformatted use [= =]. Can also be used inline.

[=
markup is ''not'' processed
but lines are reformatted
=]

markup is ''not'' processed but lines are reformatted

Horizontal line

Four or more dashes at
the beginning of a line
----
produce a "horizontal rule"

Four or more dashes at the beginning of a line


produce a "horizontal rule"

Tables

Simple tables use double pipe characters to separate cells:

|| border=1
||! head 1 ||! head 2 ||! head 3 ||
|| cell 1  ||  cell 2 ||  cell 3 ||
head 1head 2head 3
cell 1cell 2cell 3

See simple tables and advanced tables to learn more about the rich feature set of PmWiki tables.

Images

See Images

Character formatting

What to type

What it looks like

* @@Monospaced text@@
* Text with '^superscripts^'
* Text with '_subscripts_'
* deleted {-strikethrough-} text
* inserted {+underline+} text
* [+big+], [++bigger++] text
* [-small-], [--smaller--] text
  • Monospaced text
  • Text with superscripts
  • Text with subscripts
  • deleted strikethrough text
  • inserted underline text
  • big, bigger text
  • small, smaller text

Use WikiStyles to change the text color .

Page titles

The (:title:) directive sets the page's title to something other than its page name.

The name of this page is "{$Name}", and its title is "{$Title}".

The name of this page is "IncludeAll", and its title is "All pages of the documentation".

Page Description

  • The (:Description Page summary here:) directive sets the page description. The description is used by search engines, and can be displayed in search results and in page lists.
The summary description of this page is {$Description}.

The summary description of this page is .

I'm new to PmWiki, where can I find some basic help for getting started?

The Basic Editing page is a good start. From there, you can just follow the navigational links at the top or the bottom of the page (they are called Wiki Trails) to the next pages, or to the Documentation Index page, which provides an outline style index of essential documentation pages, organized from basic to advanced.

How do I include special characters such as Copyright (©) and Trademark (® or ™) on my wiki pages?

See special characters on how to insert special characters that don't appear on your keyboard.

How can I preserve line-breaks from the source text?

PmWiki normally treats consecutive lines of text as being a paragraph, and merges and wraps lines together on output. This is consistent with most other wiki packages. An author can use the (:linebreaks:) directive to cause the following lines of markup text in the page to be kept as separate lines in the output. Or a wiki administrator can set in config.php $HTMLPNewline = '<br/>'; to force literal new lines for the whole site.

Can I just enter HTML directly?

By default (and by design), PmWiki does not support the use of HTML elements in the editable markup for wiki pages. There are a number of reasons for this described in the PmWiki Philosophy and Audiences. Enabling HTML markup within wiki pages in a collaborative environment may exclude some potential authors from being able to edit pages, and pose a number of display and security issues. However, a site administrator can use the Cookbook:Enable HTML recipe to enable the use of HTML markup directly in pages.

Where can I find more documentation?

See the documentation index and the markup master index pages.


CreatingNewPages

The first step to create a new page is to edit an existing page and add a link to the page you want to create.

To link to your new page, you must choose a name for it. The best names describe the page's contents well, so that everyone can remember and type the name easily.
To create a link, surround the page name with double brackets. Typing [[my new page]] will create a link to my new page?. There's a lot you can do with double bracket links.

You can see that the links to my new page? all have question marks after them. That's because my new page? hasn't been written yet. Clicking the link as second step will take you to an edit form where you could write and finally save the new page.


Another way to create a page: in your browser's address bar (where the page URL is), replace the name of the current page with the name of the page you wish to create, and hit Enter or do whatever you would normally do to go to a new location. PmWiki will then dutifully tell you that the page you entered doesn't exist, but you can click on the "Edit" link in order to create, edit, and save the new page.

The drawback to this method is that there are no links to your new page, so you're the only person who knows it exists. It will be an orphan, unread, unlinked, unloved. That's why adding a link to an existing page or to the SideBar is a better way to create a page.


Learn more:

  • You can also organize related pages into groups, and link between pages in different groups.

How do I create a new page?

Typing [[my new page]] will create a link to the new page. There's a lot you can do with double bracket links.

Why do some new pages have a title with spaces like "Creating New Pages" and others end up with a WikiWord-like title like "CreatingNewPages"?

The default page title is simply the name of page, which is normally stored as "CreatingNewPages." However, you can override a page's title by using the (:title Creating New Pages:) directive. This is especially useful when there are special characters or capitalization that you want in the title that cannot be used in the page name.


Links

A key feature of wiki-based systems is the ease of creating hyper links (or short links) in the text of a document. PmWiki provides multiple mechanisms for creating such links.

Links to other pages in the wiki

To create an internal link to another page, simply enclose the name of the page inside double square brackets, as in [[wiki sandbox]] or [[installation]]. This results in links to wiki sandbox and installation, respectively.

PmWiki creates a link by using the text inside the double brackets. It does this by removing spaces between the words, and automatically capitalizing the first letter of each word following spaces or other punctuation (like ~). Thus [[Wiki Sandbox]], [[wiki sandbox]], and [[WikiSandbox]] all display differently but create the same link to the page titled WikiSandbox. Or in other words, PmWiki will automatically create the "link path name" using the page name in CamelCase?, but the "link text" will display in the format you have entered it.

Some PmWiki sites (default not) will recognize words written in CamelCase?, called a WikiWord, automatically as a link to a page of the same name.

Links with different link text

There are three ways to get a different link text:

  1. Hide link text. Link text within (parentheses) will not be not displayed, so that [[(wiki) sandbox]] links to WikiSandbox but displays as sandbox. For addresses actually containing parentheses, use %28 and %29 http://www.example.com/linkwith%28parenthese%29.
  2. Change link text. You can specify another link text after a vertical brace, as in [[WikiSandbox | a play area]], or you can use an arrow (->) to reverse the order of the link text and the target, as in [[a play area -> WikiSandbox]]. Both links displays as a play area.
  3. Show page title instead of page name. The use of special characters in the page name is not a problem for PmWiki, but on some servers it may be better to use only plain A-Z letters for the page "name" (which is also a filename), and set the page "title" to the extended or international characters with the (:title PageTitle:) directive within the page. The page title can be shown instead of the page name with the [[PageName|+]] link markup, e.g. page BasicEditing contains the directive (:title Basic PmWiki editing rules:) with the result that a link written as [[BasicEditing|+]] will display as Basic PmWiki editing rules.
    Since PmWiki version 2.2.14 this works also for those technical pages that have an entry in the XLPage?, without the need to add the (:title PageTitleName:) directive within that page (for more details see Localization.Localization).

On top of above ways, a suffix can be added to the end of a link, which becomes part of the link text but not of the target page name.
Note: This feature does currently not work with the [[PageName|+]] markup.

What to type

What it looks like

[[(wiki) sandbox]],\\
[[(wiki) sandbox]]es\\
[[WikiSandbox|wiki sandbox]],\\
[[WikiSandbox|wiki sandbox]]es\\
[[BasicEditing|+]]

sandbox,
sandboxes
wiki sandbox,
wiki sandboxes
Basic PmWiki editing rules

Links with tool tip

From version 2.2.14 PmWiki can show tooltip titles with the following format:

  • External link: [[http://pmwiki.org"tool tip title" | external link ]]
  • InterMap link: [[Wikipedia:Wiki"tool tip title"| InterMap link ]]
  • Linked image: [[Attach:000962.png"tool tip title" | Attach: link]]
  • Inline image: Attach:000962.png"tool tip title"

PmWiki does not support tool tip titles for internal links!

Links to nonexistent pages

Links to nonexistent pages? are displayed specially, to invite others to create the page. See Creating new pages to learn more.

Links to pages in other wiki groups

Links as written above are links between pages of the same group. To create a link to a page in another group, add the name of that other group together with a dot or slash as prefix to the page name. For example, links to Main/WikiSandbox could be written as:

What to type

What it looks like

* [[Main.WikiSandbox]]
* [[Main/WikiSandbox]]
* [[(Main.Wiki)Sandbox]]
* [[Main.WikiSandbox | link text]]
* [[Main.WikiSandbox | +]]

To link to the "default home page" of a group, the name of the page can be omitted:

* [[Main.]]
* [[Main/]]

See Wiki Group to learn more about PmWiki groups.

Category links

Categories are a way to organize and find related pages. The idea is that every page that falls into a particular subject area should have a link to a shared page containing links to other pages on that subject. These shared pages are created in the special group Category, and thus these subject areas are called "categories".

Adding a page to the category Subject is simple by adding the [[!Subject]] markup somewhere on that page. This will create a link to the page Category.Subject. So [[!Subject]] is a kind of link shortcut to the page Category.Subject. See Categories to learn more.

User page links

Similar is [[~Author]] a link shortcut to the page Author in the special group Profiles. PmWiki automatically creates this type of link for the current author, when it encounters three tilde characters (~) in a row (~~~) in the page text. The current author is the name found in the "Author" field, when you create or modify a page. The current date and time is appended when four tilde characters in a row are encountered (~~~~).

So, when the Author field contains "Author":
~~~ markup will be replaced by: Author
~~~~ markup will be replaced by: Author October 10, 2010, at 04:50 PM

Link shortcuts

[[PageName|#]] creates a reference link as shown below[1].

Links to specific locations within a page -- "anchors"

To define a location, or bookmark, within a page to which you may jump directly, use the markup [[#name]]. This creates an "anchor" that uniquely identifies that location in the page. Then to have a link jump directly to that anchor, use one of

  • [[#name|link text]] within the same page, or
  • [[PageName#name]] or [[PageName#name|link text]] for a location on another page
  • The form [[PageName(#name)]] may be useful for hiding the anchor text in a link.

For example, here's a link to the Intermaps section, below.

Notes:

  • The anchor itself must begin with a letter, not a number.
  • A link to an anchor must have the same capitalization as the anchor itself.
  • Spaces are not allowed in an anchor: "[[#my anchor]]" won't work, "[[#myanchor]]" will.
  • All anchor names in a page should be unique.

Links to actions

To link to a specific action for the current page use [[{$FullName}?action=actionname|linkname]].

Examples:

  • [[{$FullName}?action=edit|Edit]] for editing
  • [[{$FullName}?action=diff|differences]] for differences.

Links outside the wiki

Links to external sites (URLs)

Links to external sites simply begin with a prefix such as 'http:', 'ftp:', etc. Thus http://google.com/ and [[http://google.com/]] both link to Google. As with the above, an author can specify the link text by using the vertical brace or arrow syntax, as in [[http://google.com/ | Google]] and [[Google -> http://google.com]].

It is possible to set a "tooltip title" of the external link by adding it in quotes after the address:

The tooltip title of the link is "Home of PmWiki"
[[http://www.pmwiki.org/"Home of PmWiki"|link]]

link

If the external link includes (parentheses), escape these using %28 for "(" and %29 for ")" :

[[http://en.wikipedia.org/wiki/Wiki_%28disambiguation%29 | link to "Wiki (disambiguation)" ]]

link to "Wiki (disambiguation)"

The recipe Cookbook:FixURL makes it easy to encode parentheses and other special characters in link addresses.

Links to intranet (local) files

Not all browsers will follow such links (some Internet Explorer versions reportedly follow them). You can link to a file system by including the prefix 'file:///'. So file:///S:\ProjPlan.mpp and [[Shared S drive->file:///S:\]] are both valid links. On a Windows file system you may want to use network locations (eg \\server1\rootdirectory\subdirectory) rather than drive letters which may not be consistent across all users. Not all browsers will follow such links.

See also Cookbook:DirList.

Link characteristics

Links as References

Links may also be specified as References, so the target appears as an anonymous numeric reference rather than a textual reference. The following markup is provided to produce sequential reference numbering within a PmWiki page:

Formatting the link as: [[http://google.com |#]] produces: [2] as the link.

Subsequent occurrence of the reference link format on the same page will be incremented automatically as per the following example: Entering [[http://pmwiki.com |#]] produces [3], [[#intermaps |#]] produces [4], and so on for further reference links.

Intermaps

Inter Map links are also supported (see Inter Map). In particular, the Path: InterMap entry can be used to create links using relative or absolute paths on the current site (e.g., Path:../../somedir/foo.html or Path:/dir/something.gif).

Links that open a new browser window

To have a link open in another window, use %newwin%...%%:

You can also specify that links should open in a new window via the %target=_blank%...%% attribute:

The following link %target=_blank% http://pmichaud.com %%
will open in a new window.

The following link http://pmichaud.com will open in a new window.

Links that are not followed by robots

Prefix a link with %rel=nofollow% to advise robots and link checkers not to follow it.

Links and CSS Classes

PmWiki automatically gives classes to several types of links. Among other things, this enables you to format each type differently.

Note: This may be an incomplete list.

.selflink
A link to the current page. Useful in sidebars to show "you are here".
.wikilink
A link to another page within the wiki.
.urllink
A link to a page outside the wiki.

Notes

Note: The default behavior of "+" above can be overridden to display the spaced title, rather than simply the title by adding the following to config.php:

## [[target |+]] title links
Markup('[[|+', '<[[|',
  "/(?>\\[\\[([^|\\]]+))\\|\\s*\\+\\s*]]/e",
  "Keep(MakeLink(\$pagename, PSS('$1'),
                 PageVar(MakePageName(\$pagename,PSS('$1')), '\$Titlespaced')
                ),'L')");

How do I create a link that will open as a new window?

Use the %newwin% wikistyle, as in:

%newwin% http://example.com/ %%

http://example.com/

How do I create a link that will open a new window, and configure that new window?

This requires javascript. See Cookbook:PopupWindow.

How do I place a mailing address in a page?

Use the mailto: markup, as in one of the following:

* mailto:myaddress@example.com
* [[mailto:myaddress@example.com]]
* [[mailto:myaddress@example.com | email me]]
* [[mailto:myaddress@example.com?subject=Some subject | email me]]
  • myaddress [snail] example [period] com
  • myaddress [snail] example [period] com
  • email me -> mailto:myaddress [snail] example [period] com
  • email me -> mailto:myaddress [snail] example [period] com?subject=Some subject

The markup [[mailto:me@example.com?cc=someoneelse@example.com&bcc=else@example.com&subject=Pre-set Subject&body=Pre-set body | display text]] =] lets you specify more parameters like the message body and more recipients (may not work in all browsers and e-mail clients).

See also Cookbook:DeObMail for information on protecting email addresses from spammers.

How can I enable links to other protocols, such as nntp:, ssh:, xmpp:, etc?

See Cookbook:Add Url schemes How to get PmWiki to recognize additional URL schemes such as irc:, nntp:, etc.

How do I make a WikiWord link to an external page instead of a WikiPage?

Use link markup. There are two formats:

[[http://example.com/ | WikiWord]]
[[WikiWord -> http://example.com/]]

How do I find all of the pages that link to another page (i.e., backlinks)?

In the wiki search form, use link=Group.Page to find all pages linking to Group.Page.

Use the link= option of the (:pagelist:) directive, as in

(:pagelist link=SomePage list=all:)   -- show all links to SomePage
(:pagelist link={$FullName} list=all:)  -- show all links to the current page

What link schemes does PmWiki support?

See PmWiki:Link schemes Link schemes supported by PmWiki

How do I open external links in a new window or mark them with an icon?

See Cookbook:External links Configure external links to open in a new window, have a "tooltip title", or use other CSS classes

How can I use an image as a link?

Use [[Page| Attach:image.jpg ]] or [[ http://site | http://site/image.jpg ]] See Images#links

Why my browser does not follow local file:// links?

For security reasons, most browsers will only enable file:// links if the page containing the link is itself on the local drive. In other words, most browsers do not allow links to file:// from pages that were fetched using http:// such as in a PmWiki site. See also Cookbook:DirList for a workaround.


Images

To place an image into a page, enter the address (url) of the image into the markup text. Any alternate text (used for tooltips and for browsers that do not display images) is placed in double quotes immediately following the image url. A caption can follow separated by a vertical bar (|), and may include simple formatting

http://pmichaud.com/img/misc/pc.jpg"Paper clips" | [- %newwin% [[ Wikipedia:Paper_clips | Paper clips ]] are ''fun'' to work with. -]
Paper clips
Paper clips are fun to work with.

Images can also be specified as uploaded files (i.e., Attach:image.jpeg) and using InterMap links. By default PmWiki supports the following image types:

  gif jpg jpeg png

(See also Uploads and Notes below for image files that lack extensions.)

To create a link to an image (like http://pmichaud.com/img/misc/pc.jpg as opposed to displaying the image itself), use double brackets to mark the link, as in [[http://pmichaud.com/img/misc/pc.jpg]] or [[Attach:image.jpeg]].

To have an image link to another location, use the image as the link text as in

[[http://pmwiki.org/ | http://pmichaud.com/img/misc/pc.jpg"PmWiki"]]
PmWiki

or [[http://example.com|Attach:Groupname./image.jpeg]].

Captions

A caption can be added to an image using a vertical bar and the caption text.

http://pmichaud.com/img/misc/pc.jpg"Paper clips" | '''Figure 1'''
Paper clips
Figure 1

Normally, images are displayed "in line" with the surrounding text. Use %center% to center an image. Use %right% to right-align an image.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. %center%http://pmichaud.com/img/misc/pc.jpg"Paper clips"%%

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. %right% http://pmichaud.com/img/misc/gem.jpg%%

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Paper clips

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Floating images

To left or right-align an image with text wrapping around it, use the %lfloat% or %rfloat% wiki styles.

%lfloat text-align=center margin-top=5px margin-right=25px margin-bottom=5px margin-left=25px% http://pmichaud.com/img/misc/gem.jpg | '''Rock on!'''
'''The image is left-aligned, with margins set; the caption is centered; the text wraps on the right side of the image.'''

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. 

Rock on!

The image is left-aligned, with margins set; the caption is centered; the text wraps on the right side of the image.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

The [[<<]] markup breaks floating text, and the text continues at the bottom of the image.

%lfloat% http://pmichaud.com/img/misc/gem.jpg
'''The image is left-aligned, and the text wraps on the right side of the image. The text after the ''[@[[<<]]@]'' markup continues below the image.'''
[[<<]]
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 

The image is left-aligned, and the text wraps on the right side of the image. The text after the [[<<]] markup continues below the image.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Use the %lframe% or %rframe% styles to float an image and place a frame around the image and its caption. The frame can be formatted via wikistyles:

%rframe% http://pmichaud.com/img/misc/gem.jpg | '''Rock on!'''
'''The image is right-aligned, and the text wraps on the left side of the image.'''

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

%cframe width=100px bgcolor=lightblue border='3px solid red' padding=20px% http://pmichaud.com/img/misc/gem.jpg

Example to show failure to fully apply width setting:-
%cframe width=50px bgcolor=lightblue border='3px solid red' padding=20px% http://pmichaud.com/img/misc/gem.jpg

Rock on!

The image is right-aligned, and the text wraps on the left side of the image.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Example to show failure to fully apply width setting:-

Use %block rframe% to set off multiple images and caption text to be stacked vertically in a right-floating frame.

%block rframe width=300px%http://pmichaud.com/img/misc/gem.jpg\\
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\\\
http://pmichaud.com/img/misc/bubble.jpg\\
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.%%

Text subsequent to the defined block wraps to the left of the frame. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.


Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Text subsequent to the defined block wraps to the left of the frame. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Resizing images

To resize an image via wikistyles, use %width=50px% or %height=50px% in front of an image. The %thumb% wikistyle is a helpful shortcut for %width=100px%.

%width=50px% http://pmichaud.com/img/misc/bubble.jpg \
%height=50px% http://pmichaud.com/img/misc/bubble.jpg \
%thumb% http://pmichaud.com/img/misc/bubble.jpg

Note: Resizing an image via wikistyles only affects how it is displayed in a browser; it does not reduce the transfer size of the image itself - hence resizing via wikistyles is not an acceptable method of generating a page-full of images, or 'gallery'.

If you want a resized image within a link, you have to specify the size before the link as well as close it off with a %%.

%width=60%[[http://pmwiki.org/ | http://pmichaud.com/img/misc/pc.jpg"PmWiki"]]%% \
%height=60%[[http://pmwiki.org/ | http://pmichaud.com/img/misc/pc.jpg"PmWiki"]]%% \
PmWiki PmWiki

To open the link in new window, you place %newwin% before the size specification.

%newwin%[[http://pmwiki.org/ | http://pmichaud.com/img/misc/pc.jpg"PmWiki"]]%%
PmWiki

Resized images using %thumb% can also be floated with frames, as well as made into links.

%lframe thumb% [[http://pmichaud.com/img/misc/bubble.jpg | http://pmichaud.com/img/misc/bubble.jpg"Burst the bubble"]] | [-Bubble-]
%lframe thumb% http://pmichaud.com/img/misc/pc.jpg"Clip the ticket" | [-Paper Clips-]
%lframe thumb% [[DocumentationIndex | http://pmichaud.com/img/misc/gem.jpg"Visit the Documentation Index"]] | [[DocumentationIndex | [-Rock On-]]]
Burst the bubble
Bubble
Clip the ticket
Paper Clips

Images as links

To use an image as a link specify an image instead of text in the link markup.

[[PmWiki/Links | http://pmichaud.com/img/2003/atc-1.gif"Information about wiki links"]]
Information about wiki links

Notes

  • An image file that lacks a correct extension can be displayed by addition of a "false" extension to the URL. For example, if the url is http://example.com/script/tux, add a fake query string on the end with the desired extension (e.g., http://example.com/script/tux?format=.png). If query strings are unsuitable, a fragment identifier should work, e.g. http://example.com/script/tux#file.png.
  • Relative width is possible by using percentages.
%width=10pct% http://pmichaud.com/img/misc/bubble.jpg \
%height=30pct% http://pmichaud.com/img/misc/bubble.jpg 
  • Flowing text is possible, like captions, within a frame
>>lframe width=130px<<
%thumb width=130% [[http://pmichaud.com/img/misc/bubble.jpg | http://pmichaud.com/img/misc/bubble.jpg"Burst the bubble"]] | [--Long caption for an image like [[http://pmichaud.com/img/misc/bubble.jpg | the bubble]]. This is just to show some text flowing within the frame.--]
>><<
Burst the bubble
Long caption for an image like the bubble. This is just to show some text flowing within the frame.

See also

  • Cookbook:Images - adding image galleries, automatic thumbnails, background images and more.

Credits

The images on this page were obtained from http://flickr.com and are redistributed under a Creative Commons License.

Is it possible to link an image on PmWiki without using a fully qualified URL?

Yes. For images that are attachments, the general format is Attach:Groupname./image.gif. To link to an image that is on the same server, use Path:/path/to/image.gif.

Can I attach a client image file on PmWiki?

Yes, see Uploads .

How can I include a page from another group that contains an attached image?

Include the page in the normal way, ie (:include GroupName.Pagename:). In the page to be included (that contains the image) change Attach:filename.ext to Attach:{$Group}./filename.ext.

Why, if I put an image with rframe or rfloat and immediatly after that I open a new page section with ! the section title row is below the image instead of on the left side?

Because the CSS for headings such as ! contains an element clear:both which forces this behaviour. Redefine the CSS locally if you want to stop this happening, but I think the bottom border (that underlines the heading) would need further re-definition. I just use bolding for the title, and 4 dashes below ---- to separate a new section, and it saves the effort of fiddling with the core definitions.

Unlike the lframe and rframe directives, cframe does not fully honour the width setting. While the frame itself resizes to match the request, the enclosed image does not, and retains its original width. Effect is the same in IE and Fx. I've added an example beneath the standard example above.

Is it possible to disallow all images? I already disabled uploads but I also want to disallow external images from being shown on my wiki pages.

Yes, add to config.php:

DisableMarkup('img');
$ImgExtPattern = "$^";

How can I make it so that when I place an image in a page, the block of text it is in is a <p> (paragraph) rather than a <div> (division)?

If you just want it to happen for a single image (instead of all), then try putting [==] at the beginning of the line, as in:

[==] http://www.pmwiki.org/pub/pmwiki/pmwiki-32.gif

Having [==] at the beginning of a line forces whatever follows to be part of a paragraph.

Is there any way to use relative paths for images?

See Cookbook:RelativeLinks and $EnableLinkPageRelative.

Is there a way to attach a BMP and have it display rather than link?

Add to config.php the following line:
$ImgExtPattern = "\\.(?:gif|jpg|jpeg|png|bmp|GIF|JPG|JPEG|PNG|BMP)";
Note that BMP images are uncompressed and quite heavy. You may wish to convert them to PNG (lossless) or JPG (lossy) format, and thus reduce 5-20 times their filesizes.

Is there a way to have a table to the left or right of an image?

Yes, see TableAndImage.


TextFormattingRules

This page provides a more complete list of some of the markup sequences available in PmWiki. Note that it's easy to create and edit pages without using any of the markups below, but if you ever need them, they're here.

To experiment with the rules, please edit the Wiki Sandbox.


Paragraphs

To create paragraphs, simply enter text. Use a blank line to start a new paragraph.

Words on two lines in a row will wrap and fill as needed (the normal XHTML behavior). To turn off the automatic filling, use the (:linebreaks:) directive above the paragraph.

  • Use \ (single backslash) at the end of a line to join the current line to the next one.
  • Use \\ (two backslashes) at the end of a line to force a line break.
  • Use \\\ (three backslashes) at the end of a line to force 2 line breaks.
  • Use [[<<]] to force a line break that will clear floating elements.

Indented Paragraphs (Quotes)

Arrows (->) at the beginning of a paragraph can be used to produce an indented paragraph. More hyphens at the beginning (--->) produce larger indents.

->Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal.
Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal.

Inverted Arrows (-<) at the beginning of a paragraph can be used to produce a paragraph with a hanging indent. Adding hyphens at the beginning (---<) causes all the text to indent.

-<Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal. 
Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal.
--<Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal.  And that food would be good too.
Four score and seven years ago our fathers placed upon this continent a new nation, conceived in liberty and dedicated to the proposition that all men are created equal. And that food would be good too.

Blocks of text to which (:linebreaks:) has been applied can be indented by preceding the first line of the block with indention arrows (->) and aligning subsequent lines under the first. An unindented line stops the block indentation. See Cookbook:Markup Tricks for an example.

Bulleted and Numbered Lists

Bullet lists are made by placing asterisks at the beginning of the line. Numbered lists are made by placing number-signs (#) at the beginning of the line. More asterisks/number-signs increases the level of bullet:

* First-level list item
** Second-level list item
### Order this
#### And this (optional)
### Then this
** Another second-level item
* A first-level item: cooking
## Prepare the experiment
### Unwrap the pop-tart
### Insert the pop-tart into the toaster
## Begin cooking the pop tart
## Stand back
  • First-level list item
    • Second-level list item
      1. Order this
        1. And this (optional)
      2. Then this
    • Another second-level item
  • A first-level item: cooking
    1. Prepare the experiment
      1. Unwrap the pop-tart
      2. Insert the pop-tart into the toaster
    2. Begin cooking the pop tart
    3. Stand back
# A list is terminated
by the first line that is not a list.
# Also terminate a list using the escape sequence [@[==]@]
[==]
# Continue a list item by lining
  up the text with leading whitespace.
# Use a forced linebreak \\
  to force a newline in your list item.
  1. A list is terminated

by the first line that is not a list.

  1. Also terminate a list using the escape sequence [==]

  1. Continue a list item by lining up the text with leading whitespace.
  2. Use a forced linebreak
    to force a newline in your list item.
## Text between list items can cause numbering to restart
## %item value=3% this can be dealt with
  1. Text between list items can cause numbering to restart
  2. this can be dealt with

Also see: PmWiki:ListStyles, Cookbook:WikiStylesPlus.

Definition Lists

Powerful new* feature
When you define terms using this markup
PmWiki will recognize them as PageTextVariables
that you can use on any page or PageList.
* Added in PmWiki version 2.2.0

Definition lists are made by placing colons at the left margin (and between each term and definition):

:term:definition of term
term
definition of term

Whitespace Rules

Whitespace indentation in lists. Any line that begins with whitespace and aligns with a previous list item (whether bulleted, numbers or definitional) is considered to be "within" that list item. Text folds and wraps as normal, and the (:linebreaks:) directive is honored.

# First-level item\\
  Whitespace used to continue item on a new line
# Another first-level item
  # Whitespace combined with a single # to create a new item one level deeper
  1. First-level item
    Whitespace used to continue item on a new line
  2. Another first-level item
    1. Whitespace combined with a single # to create a new item one level deeper

Otherwise, lines that begin with whitespace are treated as preformatted text, using a monospace font and not generating linebreaks except where explicitly indicated in the markup. Note to administrators: Starting with version 2.2.0-beta41, this feature can be modified using $EnableWSPre. (Another way to create preformatted text blocks is by using the [@...@] markup.)

Horizontal Line

Four or more dashes (----) at the beginning of a line produce a horizontal line.

Emphasis and character formatting

  • Enclose text in doubled single-quotes (''text''), i.e., two apostrophes, for emphasis (usually italics)
  • Enclose text in tripled single-quotes ('''text'''), i.e. three apostrophes, for strong (usually bold)
  • Enclose text in five single-quotes ('''''text'''''), or triples within doubles (five apostrophes), for strong emphasis (usually bold italics)
  • Enclose text in doubled at-signs (@@text@@) for monospace text
  • Use [+large+] for large text, [++larger++] for larger, [-small-] for small text, and [--smaller--] for smaller.
  • Emphasis can be used multiple times within a line, but cannot span across markup line boundaries (i.e., you can't put a paragraph break in the middle of bold text).
  • '~italic~' and '*bold*' are available if enabled in config.php

Other styling

'+big+', '-small-', '^super^', '_sub_', 

{+insert or underscore+}, 

{-delete or strikethrough or strikeout-}

big, small, super, sub,

insert or underscore,

delete or strikethrough or strikeout

  • `WikiWord WikiWord neutralisation

See also Wiki Styles for advanced text formatting options.

References

  • Use words and phrases in double brackets (e.g., [[text formatting rules]]) to create links to other pages on this wiki.
  • On some PmWiki installations, capitalized words joined together (e.g., WikiWords) can also be used to make references to other pages without needing the double-brackets.
  • Precede URLs with "http:", "ftp:", "gopher:", "mailto:", or "news:" to create links automatically, as in http://www.pmichaud.com/toast.
  • URLs ending with .gif, .jpg, or .png are displayed as images in the page
  • Links with arbitrary text can be created as either [[target | text]] or [[text -> target]]. Text can be an image URL, in which case the image becomes the link to the remote url or WikiWord.
  • Anchor targets within pages (#-links) can be created using [[#target]].

See Links for details.

Headings

Headings are made by placing an exclamation mark (!) at the left margin. More exclamation marks increase the level of heading. For example,

!! Level 2 Heading
!!! Level 3 Heading
!!!! Level 4 Heading
!!!!! Level 5 Heading

Level 2 Heading

Level 3 Heading

Level 4 Heading

Level 5 Heading

Note that level 1 heading is already used as page title (at least in the PmWiki skin), so you should start with level 2 headings to create well formed, search engine optimized web pages.

See Cookbook:Numbered Headers for numbered headings.

Escape sequence

Anything placed between [= and =] is not interpreted by PmWiki, but paragraphs are reformatted. This makes it possible to turn off special formatting interpretations and neutralise WikiWords that are not links (even easier is to use a tick ` in front, like `WikiWord).

For preformatted text blocks, use the [@...@] markup. It does neither reformat paragraphs nor process wiki markup:

[@
Code goes here like [[PmWiki.PmWiki]]
'$CurrentTime $[by] $AuthorLink:  [=$ChangeSummary=]'; #just some code
@]
Code goes here like [[PmWiki.PmWiki]]
'$CurrentTime $[by] $AuthorLink:  [=$ChangeSummary=]'; #just some code

The multiline [@...@] is a block markup, and in order to change the styling of these preformatted text blocks, you need to apply a "block" WikiStyle.

%block blue%[@ 
  The font color of 
  this text is blue
@]
 
  The font color of 
  this text is blue

It is also useful to use [= =] within other wiki structures, as this enables the inclusion of new lines in text values. The example below shows how to include a multi-line value in a hidden form field.

(:input hidden message "[=Line1
Line2=]":)

Comments

(:comment Some information:) can be very kind to subsequent authors, especially around complicated bits of markup.

Special Characters

When creating pages it's common to use commercial trademarks, copyright, umlaut, and other non-keyboard symbols. therefore it's important that you have the means to input these special characters.

ISO Standard codes

PmWiki supports the HTML special character listings by the w3c. W3C Page of Special Character codes ISO standard.

Here are some samples:

&#169;  
&#188;  &frac14;
&#189;  &frac12;
&#174;  &#181;  &#168;

© ¼ ¼ ½ ½ ® µ ¨

&#198;  32&#176;  Un&#239;ted St&#228;tes  &#182;  &#165;Yen  PmWiki&#8482;

Æ 32° Unïted Stätes ¶ ¥Yen PmWiki

For a nice table with all available special characters, see List of Unicode characters at Wikipedia.

Other ways to do it:

Character Map

Find the "Character Map" utility in your computer's System Tools folder. Click the symbol you're interested in, and note the keystroke information at the bottom of the box. You execute these by holding "Alt" while keying the numbers on the numerical keypad of your keyboard (not the numbers across the top of the board).

&#169; = Alt+0169 = ©
&#174; = Alt+0174 = ®
&#176; = Alt+0176 = ° (degrees)

Paste

  • Use Word or another desktop application to create your text with the special characters that you want. Copy and paste the text to the wiki page you're editing or creating.
  • Find an instance of a special character in an online document; copy and paste the character to your wiki page: ©

There's a list of special characters at PmWiki:SpecialCharactersList. There's another illustration at PmWiki:Characters

Tables

Tables are defined by enclosing cells with '||'. A cell with leading and trailing spaces is centered; a cell with leading spaces is right-aligned; all other cells are left-aligned. An empty cell will cause the previous cell to span multiple columns. (There is currently no mechanism for spanning multiple rows.) A line beginning with '||' specifies the table attributes for subsequent tables. A '!' as the first character in a cell provides emphasis that can be used to provide headings.

||border=1 width=50%
||!Table||!Heading||!Example||
||!Left   || Center || Right||
||A       ||!  a B   ||     C||
||        || single ||      ||
||        || multi span   ||||
TableHeadingExample
LeftCenterRight
Aa BC
 single 
 multi span

See Table Directives for advanced tables.

Can't find it here?

See Markup Master Index.


Markup Master Index

This page contains the most frequently used wiki markup, briefly. Follow the links in each section to learn more.

Links

See Links

External links

http://example.com
[[http://example.com]]
[[http://example.com | link text]]
[[link text -> http://example.com]]

Page links

[[PageName]]
[[page name]]
[[page (name)]]
[[PageName | link text]]
[[PageName | + ]] (titled link)
[[PageName | # ]] (anonymous numerical reference link)
[[link text -> PageName]]
[[#anchor]] (to create an anchor)
[[#anchor | link text]] (to refer to an anchor)
[[PageName#anchor | link text]] (to refer to an anchor in another page)

See also WikiWord on how to enable WikiWord links.

WikiGroup links

See Links and Categories

[[GroupName/]] or [[Group name/]]
[[GroupName.]]
[[GroupName/PageName]] or [[GroupName/page name]]
[[(GroupName.)page name]]
[[~Author Name]]
[[!Category Name]]

InterMap links

See InterMap

[[Path:/path/local_document.html]]
[[Wikipedia:WikiWikiWeb]]

Email links

mailto:someone@example.com
[[(mailto:)someone@example.com]]
[[mailto:someone@example.com | display text]]
[[display text -> mailto:someone@example.com]]

Upload links

See Uploads and Images

Attach:file.odt
[[(Attach:)file.odt]]
[[Attach:file.odt | alternative text ]]
[[Attach:file with spaces.pdf]]
[[Attach:Groupname./file with spaces.pdf]]

Images

See Images and Uploads

Images as Images

http://example.com/image.gif
http://example.com/image.gif"alt text"
Attach:image.gif"My image"
Attach:Groupname./image.gif"image in another group"
Attach:Groupname.Pagename/image.gif"image on another page"
%lfloat% Attach:image.gif | Caption %% (could be %rfloat%, %center%, %rframe%, %lframe% )
%width=200px% Attach:image.gif %%
%thumb% Attach:image.gif %%

Images as links

[[Attach:image.gif]]
[[(Attach:)image.gif]]
[[PageName | Attach:image.gif"alt text"]]
[[http://example.com/ | Attach:image.gif"alt text"]]
%rframe thumb% [[Attach:image.gif | Attach:image.gif"alt text"]] | Caption

Start-of-line markup

See Text formatting rules

Lists

See List Styles, Wiki styles and Cookbook:Outline lists

* unordered list
** deeper list
# ordered list
# %item value=#% arbitrary start number
# %decimal%, %roman%, %ROMAN%, %alpha%, %ALPHA%
:term:definition

Also

Q: start a question paragraph
A: start an answer paragraph

Headings

!! Heading
!!! Deeper heading

Paragraph blocks

-> indented text
-< hanging indent
<space> preformatted text
[@...@] preformatted block
---- (horizontal rule)
blank line is vertical space
\ at end of line joins next line
\\ at end of line produces a line break
\\\ at the end of a line produces a blank line, even within a list item
[[<<]] produces a line break that clears floating content

Division blocks

See Block markup, Wiki styles and Page directives

>>wikistyle<<
>><<
(:div class="" style="":)
(:divend:)

Text markup

See Text formatting rules

Character format

''emphasized''
'''strong'''
'''''strong emphasis'''''
@@monospaced@@
[-small-], [--smaller--]
[+big+], [++bigger++]
'-small-', '+big+'
'^superscript^', '_subscript_'
{+inserted+} (underscore)
{-deleted-} (strikethrough)
[@escaped code@]
[=escaped text=]

Posting markup

~~~ (author's signature)
~~~~ (author's signature and date)
(:encrypt phrase:) -- replaced with encrypted form of phrase

Tables

Plain rows and columns of text

See Tables

||table attributes
||!table caption!||
||left aligned || centered || right aligned||
||!column heading||
||spanned columns ||||||

Structured tables

See Table directives

(:table attr:)
(:cellnr attr:)
(:cell attr:)
(:tableend:)

Directives

Page directives

See Page directives

(:redirect PageName:)
(:(no)spacewikiwords:)
(:(no)linkwikiwords:)
(:(no)linebreaks:)
(:nl:) insert newline in the *markup* only if one isn't present. The purpose of (:nl:) is to be able to write things like:
(:include Page1:)(:nl:)(:include Page2:)
which guarantees that the first line of Page2 is treated as a separate line from the last line of Page1, but without inadvertently generating a blank line between them.

Display

See Page directives Group headers

(:noheader:), (:nofooter:)
(:notitle:)
(:noleft:), (:noright:)
(:nogroupheader:), (:nogroupfooter:)
(:noaction:)

Metadata

See Page directives, Comment markup, Page variables

(:title text:)
(:description text:)
(:comment text:)
{Group/PageName$:Var} includes from (:name:text:)

Include

See Include other pages, Page text variables

(:include PageName:)
(:include PageName#start#end lines=n paras=n:)
(:include Page1 Page2 Page3:)
{Group/PageName$:Var} includes from (:name:text:)

Conditional markup

See Conditional markup

(:if (!) cond param:)...(:ifend:)
(:if (!) cond param:)...(:else:)...(:ifend:)
(:if (!) cond param:)...(:elseif (!) cond param:)...(:ifend:)

Pagelists

See Page lists

(:searchbox label=label order=-time:)
(:searchresults incl -excl group=abc fmt=def:)
(:pagelist incl -excl group=abc fmt=def:)

Other directives

See Page directives

(:PageDirectives#markup:) [=...=]
(:markup:)...(:markupend:)
(:markup class=horiz:)...(:markupend:)
(:markup caption='...':)...(:markupend:)
(:messages:)

Forms

See Forms

(:input form method=get action=url enctype=multipart/form-data:)
(:input default name=xyz value="abc":)
(:input text name=first value="Bob" size=20:)
(:input textarea name=xyz [=value=] rows=2 cols=80:)
(:input submit name=post value="Go" accesskey=g:)
(:input reset:)
(:input hidden name=action value=edit:)
(:input radio name=xyz value="abc" checked=1:)
(:input checkbox name=xyz value="abc" checked=1:)
(:input password name=authpw:)
(:input file name=upload:)
(:input image name=xyz src="http:..." alt="Alt Text":)
(:input select name=xyz value="val1" label="Value 1":)
(:input select name=xyz value="val2" label="Value 2":)
(:input end:)

See also PmWiki Edit forms.

Wiki trails

See Wiki trails

<<|[[TrailPage]]|>>
<|[[TrailPage]]|>
^|[[TrailPage]]|^

Page variables

See Page variables, Page text variables, Page lists

{$variable}
{pagename$variable}
(:name:description:) sets a page text variable

Expressions

See Markup expressions

{(function args)}

Uploads

PmWiki can be configured to allow authors to upload and store files and images (known as attaching them). These attachments may then be referenced from any page.

Note: PmWiki is distributed with uploads disabled by default. See Uploads Admin for information about how to enable and configure the upload feature.
Note2: Uploads can be configured site-wide, by-group, or by-page; see Uploads Admin for details. This determines whether all uploads go in one directory for the site, an individual directory for each group, or an individual directory for each page. The default is to organize uploads by group.

Attach: Syntax

To add or link to an attachment, an author edits a page to include the markup "Attach:" followed by a name of an attachment (e.g., "Attach:resume.pdf"). When the page is displayed, the Attach: markup becomes one of the following:

  • A link to the named attachment (if uploaded, ie already in the upload directory)
  • A link to a form whereby the author can specify a file to be uploaded and used as the new attachment (if not yet uploaded, ie not in the upload directory)
  • If the attachment is an image file with an extension such as .gif, .jpeg, or .png, it is displayed as an image.

The behaviour of links can be modified to

  • prevent an image attachment from displaying as an image, place it in double brackets (e.g., [[Attach:image.jpg]]).
  • have a link to an attachment appear without the "Attach:" at the beginning of the link, use [[(Attach:)file.ext]].

Attachments on other pages and groups

To link to an uploaded attachment (image or file) from another group, you simply refer the group itself (make sure "Groupname" has the dot in it).

Attach:Groupname./file_name.ext (note the dot after the groupname)

If PmWiki is configured with an individual directory per page use

Attach:Pagename/file_name.ext (Pagename is in the same WikiGroup)
Attach:Groupname.Pagename/file_name.ext

Names with spaces

To link to a filename with spaces in it use the bracket link notation, eg

[[Attach:a filename with spaces.txt]]

"Embedding in the page" an image with spaces is not supported: just upload the images with names without spaces, and use the markup Attach:image.jpg.

The following workaround is possible, but is unsupported and not recommended:

[[#blank | Attach:image space.jpeg]]

International characters in file names

See UploadsAdmin and $UploadNameChars.

Listing Uploaded Files On A Page

To list files that have been uploaded, use the markup: (:attachlist:)

This will list attachments to the current group or page, depending whether attachments are organised per group or per page; each instance includes a link to the attachment for viewing or downloading. A list of attachments is also shown as part of the uploads page form.

Upload Form / Upload Replacement

One can go directly to the upload form by appending "?action=upload" to the URI for any page that has file uploads enabled by the Wiki Administrator. Replace a file by simply uploading a new version of the file with the same name.

  • Be sure to clear your browser cache after replacing an upload. Otherwise, it may appear that the original upload is still on the server.

If you put $EnableUploadVersions=1; in your local/config.php, the old versions of the same files are renamed and not removed.

Type and Size Restrictions

For security reasons, the upload feature is disabled when PmWiki is first installed. When enabled uploads are restricted as to the types and sizes of files that may be uploaded to the server (see UploadsAdmin). PmWiki's default configuration limits file sizes to 50 kilobytes and file extensions to common types such as ".gif", ".jpeg", ".doc", ".txt", and ".pdf".

In addition, the administrator can configure the system to require an upload password--see Passwords and PasswordsAdmin.

By default the upload allows the following extensions. Note that by default, no file extension is required.

'gif','jpg','jpeg','png','bmp','ico','wbmp','svg','xcf'        # images

'mp3','au','wav','ogg','flac',                                 # audio
'ogv','mp4','webm','mpg','mpeg','wmf','mov','qt','avi',        # video
'zip','7z','gz','tgz','rpm','hqx','sit',                       # archives
'doc','ppt','xls','mdb',                                       # MSOffice
'exe',                                                         # executables
'pdf','psd', 'ps','ai','eps',                                  # Adobe
'htm','html','css','fla','swf',                                # web stuff
'txt','rtf','tex','dvi',                                       # text files
'odt','ods','odp','odg',                                       # OpenOffice.org 
'epub','kml','kmz',''                                          # misc

Removal

At present uploaded files can only be deleted from the server by the wiki administrator. Any uploads-authorized user may over-write an existing file by uploading another of the same name and extension to the same location.

The administrator may remove an uploaded file by accessing the server via ftp (or via a control panel, if the host offers such a feature). The recipe Cookbook:Attachtable allows the deletion of the files from the wiki.

When I upload a file, how do I make the link look like "file.doc" instead of "Attach:file.doc Δ"?

Use parentheses, as in [[(Attach:)file.doc]]. There is also a configuration change that can eliminate the Attach: -- see Cookbook:AttachLinks.

Why can't I upload files of size more than 50kB to my newly installed PmWiki?

Out of the box PmWiki limits the size of files to be uploaded to 50kB. Add

$UploadMaxSize = 1000000; # limit upload file size to 1 megabyte
to your config.php to increase limit to 1MB (for example). See UploadsAdmin for how to further customize limits. Note that both PHP and webservers also place their own limits on the size of uploaded files.

Why does my upload exit unexpectedly with "Incomplete file received"?

You may be running out of space in a 'scratch' area, used either by PmWiki or by PHP. On *nix, check that you have sufficient free space in /tmp and /var/tmp.

How do I make it so that the upload link still allows one to make another upload (if someone wants to replace the old version of a file with a newer version, for example). Currently you only get the upload link when there is no file in the upload directory.

Use the Attach page action, and click on the delta symbol (Δ) shown against each of files listed. If you can't see the attach action either uploads are not enabled, you are not authorized to upload, or the attach action has been commented out or is missing. See also available actions.

How do I hide the "Attach:" for all attachments

See Cookbook:AttachLinks, note that this does not currently work for [[Attach:my file.ext]] .

How can I link a file that have a 4-letter file extension such like 'abc.pptx'?

See Cookbook:Upload Types

How can I prevent others from using the url's of my images on their site

See Cookbook:Prevent Hotlinking Prevent hotlinking of uploaded files


Tables

Table basics

PmWiki has two types of table markup; the markup described in this page is useful for creating simple tables with lots of small cells, while table directive markups help with larger scale tables. For more possibilities with table formatting see Cookbook:Rowspan in simple tables and Cookbook:Formatting tables.

Tables are created via use of double pipe characters: ||. Lines beginning with this markup denote rows in a table or a formatting line. Within table row lines the double-pipe is used to delimit cells. In the examples below a border is added for illustration (the default is no border).

The first line in the markup contains formatting commands for the table. It only has double pipe characters at the start of the line.

Basic table
|| border=1
|| cell 1 || cell 2 || cell 3 ||
|| cell 1 || cell 2 ||
cell 1cell 2cell 3
cell 1cell 2

Header cells can be created by placing ! as the first character of a cell. Note that these are table headers, not headings, so it doesn't extend to !!, !!!, etc.

Table headers
|| border=1
||! cell 1 ||! cell 2 ||! cell 3 ||
|| cell 1  ||  cell 2 ||  cell 3 ||
cell 1cell 2cell 3
cell 1cell 2cell 3

A table can have a caption, indicated by ||!caption!||. Any caption must appear prior to other rows of the table.

Table caption
|| border=1
||! A special table !||
||! cell 1 ||! cell 2 ||! cell 3 ||
|| cell 1  ||  cell 2 ||  cell 3 ||
A special table
cell 1cell 2cell 3
cell 1cell 2cell 3

Formatting cell contents

Cell contents may be aligned left, centered, or aligned right.

  • To left-align contents, place the cell contents next to the leading ||.
  • To center contents, add a space before and after the cell contents.
  • To right-align contents, place a space before the cell contents and leave the cell contents next to the trailing ||.
Cell alignments
|| border=1 width=100%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
cell 1cell 2cell 3
left-alignedcenteredright-aligned
Default cell alignments
|| border=1 width=100%
||!cell default||!cell left ||
||default-aligned||left-aligned ||
cell defaultcell left
default-alignedleft-aligned

Note that header and detail cells have different default alignments.

To get a cell to span multiple columns, follow the cell with empty cells. (At present there is no markup for spanning rows.)

Column spanning
|| border=1 width=100%
|| |||| right column ||
|| || middle column ||||
|| left column ||||||
|| left column || middle column || right column ||
 right column
 middle column
left column
left columnmiddle columnright column

Table attributes

Any line that begins with || but doesn't have a closing || sets the table attributes for any tables that follow. These attributes can control the size and position of the table, borders, background color, and cell spacing. (In fact these are just standard HTML attributes that are placed in the <table> tag.)

Use the width= attribute to set a table's width, using either a percentage value, an absolute size, or *.

Table width
|| border=1 width=100% 
|| cell 1 || cell 2 || cell 3 ||
|| c1 || cellcellcellcell2 || cell 3 ||
cell 1cell 2cell 3
c1cellcellcellcell2cell 3

The border= attribute sets the size of a table's borders.

Bordered table
|| border=10 width=70%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
cell 1cell 2cell 3
left-alignedcenteredright-aligned
Borderless table
|| border=0 width=70%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
cell 1cell 2cell 3
left-alignedcenteredright-aligned

Use align=center, align=left, and align=right to center, left, or right align a table. Note that align=left and align=right create a floating table, such that text wraps around the table.

Table alignment: center
|| border=1 align=center width=50%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
Notice how text does not wrap with a table using "align=center".
cell 1cell 2cell 3
left-alignedcenteredright-aligned

Notice how text does not wrap with a table using "align=center".

Table alignment: left
|| border=1 align=left width=50%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
Notice how text wraps to the right of a table using "align=left".
cell 1cell 2cell 3
left-alignedcenteredright-aligned

Notice how text wraps to the right of a table using "align=left".

Table alignment: right
|| border=1 align=right width=50%
||!cell 1      ||! cell 2  ||!       cell 3||
||left-aligned || centered || right-aligned||
Notice how text wraps to the left of a table using "align=right".
cell 1cell 2cell 3
left-alignedcenteredright-aligned

Notice how text wraps to the left of a table using "align=right".

Note: to get a table to align left (but not "float left") requires CSS, as in

||style="margin-left:0px;"

The bgcolor= attribute sets the background color for a table. At present there is no way to specify the color of individual rows or cells in this type of table (but see Cookbook:FormattingTables).

|| border=1 align=center bgcolor=yellow width=70%
||!cell 1    ||! cell 2 ||!     cell 3||
||left-align || center  || right-align||
cell 1cell 2cell 3
left-aligncenterright-align

How do I create a basic table?

Tables are created via use of the double pipe character: ||. Lines beginning with this markup denote rows in a table; within such lines the double-pipe is used to delimit cells. In the examples below a border is added for illustration (the default is no border).

Basic table
|| border=1 rules=rows frame=hsides
|| cell 1 || cell 2 || cell 3 ||
|| cell 1 || cell 2 || cell 3 ||
cell 1cell 2cell 3
cell 1cell 2cell 3

How do I create cell headers?

Header cells can be created by placing ! as the first character of a cell. Note that these are table headers, not headings, so it doesn't extend to !!, !!!, etc.

Table headers
|| border=1 rules=cols frame=vsides
||! cell 1 ||! cell 2 ||! cell 3 ||
|| cell 1  ||  cell 2 ||  cell 3 ||
cell 1cell 2cell 3
cell 1cell 2cell 3

How do I obtain a table with thin lines and more distance to the content?

"Thin lines" is tricky and browser dependent, but the following works for Firefox and IE (Nov. 2009):

Thin lines and cell padding
||border="1" style="border-collapse:collapse" cellpadding="5" width=66%
||!Header ||! Header || '''Header'''||
||cells   ||  with   ||      padding||
||        ||         ||             ||
HeaderHeaderHeader
cellswithpadding
   

How do I create an advanced table?

See table directives

My tables are by default centered. When I try to use '||align=left' they don't align left as expected.

Use ||style="margin-left:0px;" instead.

How can I specify the width of columns?

You can define the widths via custom styles, see Cookbook:FormattingTables and $TableCellAttrFmt. Add in config.php : $TableCellAttrFmt = 'class=col$TableCellCount';

And add in pub/css/local.css :
table.column td.col1 { width: 120px; }
table.column td.col3 { width: 40px; }

How can I display a double pipe "||" in cell text using basic table markup?

Escape it with [=||=] to display || unchanged.

How to I apply styles to the elements of the table, like an ID to the table row, or a class/style to the TD?

See $WikiStyleApply.


Table directives

There are six directives for table processing. All must be at the beginning of a line to have any effect.

(:table [attr...]:)

Generates a new HTML <table> tag with the attributes provided in attr.... Closes the previous table, if any. Valid attributes and values are:

  • border (a positive integer)
  • bordercolor (a color name or hex number; doesn't display in all browsers)
  • cellspacing (a positive integer indicating the space between cells)
  • cellpadding (a positive integer indicating the interior border of a cell)
  • width (a positive integer or percent)
  • bgcolor (a color name or hex number)
  • align (left, center or right)
  • summary (does not display; used primarily to help visually disabled people navigate)

(:cellnr [attr...]:), (:cell [attr...]:), (:headnr [attr...]:), (:head [attr...]:)

  • The (:head:) directive opens a new "header cell" of the table (creates <th> tag in HTML).
  • The (:cell:) directive opens a new "regular cell" of the table (creates <td> tag in HTML).
  • The directives (:headnr:) and (:cellnr:) open a new cell on a new row in the table.

These directives close any previous cell and/or row. Note, the (:head:) and (:headnr:) directives exist from PmWiki version 2.2.11 or newer.

Valid attributes and values are:

  • align (left, center or right)
  • valign (top, middle or bottom) * default is "top", see note below
  • colspan (a positive integer)
  • rowspan (a positive integer)
  • bgcolor (a color name or hex number)
  • width (a positive integer or percent)
  • class (a CSS class of the cell)
  • style (custom CSS styles of the cell)

(:tableend:)

Closes the previous table cell and closes off any table. Generates </th>, </td>, </tr>, and </table> tags as needed.

* valign attribute

If not already set, PMWiki will automatically include the attribute valign='top' with all (:cell[nr]:) and (:head[nr]:). Pm said "Table Directives were created for layout purposes and in that case it makes the most sense for each cell (column) to have its content at the top of the row. The attribute is placed in each cell and not in the row because certain browsers didn't recognize valign='top' in the row tag.

Notes

For the table, cell, and cellnr tags the author can specify any attributes that would be valid in the HTML <table> or <td> tags. Thus you can specify rowspan, colspan, etc. arguments to build arbitrary tables. However, it's not possible to nest a (:table:) inside of a (:cell:) or (:cellnr:) -- the next paragraph explains why.

Many are likely to ask why we didn't just use the standard HTML table markup (<table>, <tr>, <td>, <th>) instead of creating a new markup, and allowing nested tables as a result. There are two answers: first, the HTML table markup is very ugly for naive authors (see PmWiki.Audiences and PmWikiPhilosophy #2), and second, it'd be very easy for authors to create tables that are incorrect HTML and that display incorrectly (or not at all) on some browsers. Even seasoned web professionals sometimes get the table markup wrong, so it's a bit unrealistic to expect the average author to always get it right, or to be able to read arbitrary HTML table markup that someone else has created.

Common comment: Surely, the average or naive author would not be writing HTML directly, but using a tool, such as FrontPage, or even MSWord, to generate the HTML. This would be a lot simpler than learning even the simplest PmWiki markups.
Pm's Response: And once the HTML has been generated and posted, how is someone else going to edit or modify the table if they don't have the original FrontPage or MSWord file used to create it? Remember that we're talking about collaborative authoring. The HTML that those packages generate is among the hardest to read and edit of all!

It's difficult to write the code needed to make PmWiki understand and fix arbitrary table markup, so PmWiki uses the simplified version above. Still, this version is able to handle most table requirements (with the possible exception of nested tables).

And, this is not to say that nested HTML tables are impossible in PmWiki --they just can't be easily created by wiki authors using the default wiki markup. A site administrator can of course create header/footer HTML code and other local customizations that make use of nested tables.

Example 1. A table using table directive markup.

"&nbsp;" is a non-breaking space in html. Place it in a cell if a cell is to be empty or the border of the cell will not be drawn properly.

(:table border=1 cellpadding=5 cellspacing=0:)
(:head:) a1
(:cell:) b1
(:cell:) c1
(:cell:) d1
(:headnr:) a2
(:cell:) b2
(:cell:) c2
(:cell:) &nbsp;
(:tableend:)
a1 b1 c1 d1
a2 b2 c2  

In HTML, this is the same as

<table border='1' cellpadding='5' cellspacing='0'>
  <tr>
    <th>a1</th>
    <td>b1</td>
    <td>c1</td>
    <td>d1</td>
  </tr>
  <tr>
    <th>a2</th>
    <td>b2</td>
    <td>c2</td>
    <td>&nbsp;</td>
  </tr>
</table>

Floating Table with bulleted navigation list

What if you wanted to create a nice little table like a table of contents in a page like this? In this example, the table is floating right and contains some links in a bulleted list. This is a nice demonstration of how it's possible to build a little table of contents in the page, which might navigate to other pages just within the same wiki group. Note that having a bulleted list won't work in a ordinary table - it only works inside an table created with table directives such as the example code used here.

(:table border=1 width=30% align=right bgcolor=#cccc99 cellspacing=0 :)
(:cellnr:)
'''Navigation Links'''
(:cellnr:)
*[[Tables]]
*[[Table directives]]
(:tableend:)

Navigation Links

(:table border=1 width=30% align=right bgcolor=#cccc99 cellspacing=0 :)
(:cellnr colspan=2 align=center:)
'''Navigation Links'''
(:cellnr align=center:)
[[Tables]]
(:cell align=center:)
[[Table directives]]
(:tableend:)

Navigation Links

Tables

Table directives

Looking at the markup here, notice that we have used a #cccc99 hex color for the table background. Also, the (:cellnr:) markup creates a new row, a new cell and closes the row at the end.

You could take this concept a little further: since you might want each page in the group to contain the same table of contents, you can make ONE table like the above and put it in its own page. Then use an include on any of your pages and bring in the table. The float (align) property will be honored in each page where it's included.

Can I define table headers using the table directive markup?

Yes, with PmWiki version 2.2.11 or newer. See also Cookbook:AdvancedTableDirectives.

Is it possible to do nested tables?

Yes, if you nest simple tables inside advanced tables. See also Cookbook:AdvancedTableDirectives.

Is it possible to add background images to tables and table cells?

Yes, see Cookbook:BackgroundImages.

Is it possible to apply styles to the elements of the table, like an ID to the table row, or a class/style to the TD?

Yes, see $WikiStyleApply.

Is it possible to automatically generate columns or rows in tables, i.e. without having to do a lot of counting?

Yes, this is possible with the Cookbook:CreateColumns recipe - it allows you to specify a certain number of columns, and/or to specify a certain number of items per column. Plus, someone has provided some similar markup on the TableDirectives-Talk page.


WikiStyles

WikiStyle basics

WikiStyles allow authors to modify the color and other styling attributes of the contents of a page. A WikiStyle is written using percent-signs, as in %red% or %bgcolor=lightblue%.

WikiStyle attributes

The style attributes recognized within a WikiStyle specification are:

------------ CSS ------------- --HTML--
 bgcolor
 background-color
 border1
 color
 background-color
 border
 display
 float
 font-size
 font-family
 font-weight
 font-style
 height*
 list-style
 margin1
 padding1
 text-align
 text-decoration
 white-space
 width* 
 accesskey 
 align
 class
 hspace 
 id 
 target 
 rel 
 vspace 
 value
 Special: define, apply

The attributes in the first two columns correspond to the cascading style sheet (CSS) properties of the same name. The attributes in the last column apply only to specific items:

  • class= and id= assign a CSS class or identifier to an HTML element
  • target=name opens links that follow in a browser window called "name"
  • rel=name in a link identifies the relationship of a target page
  • accesskey=x uses 'x' as a shortcut key for the link that follows
  • value=9 sets the number of the current ordered list item
    • The width and height attributes have asterisks because they are handled specially for <img .../> tags. If used by themselves (i.e., without anything providing an "apply=" parameter to the WikiStyle), then they set the 'width=' and 'height=' attributes of any <img ... /> tags that follow. Otherwise, they set the 'width:' and 'height:' properties of the element being styled.
    1. margin, padding, and border can be suffixed by -left, -right, -top, and -bottom

WikiStyles versus CSS styles

WikiStyles, as written in the wiki page, are not exactly CSS styles or CSS classes. WikiStyles allow authors to use both pre-defined by the administrator CSS classes, and to define new combinations of styles, without any need to edit/update local CSS files on the server.

Note that PmWiki allows advanced authors to use of class= and style= in tables and division blocks, but these are raw HTML attributes, and not WikiStyles, knowledge of CSS is required to use them.

Text color and font

The most basic use of WikiStyles is to change text attributes such as color, background color, and font. PmWiki defines several WikiStyles for changing the text color to %black%, %white%, %red%, %yellow%, %blue%, %gray%, %silver%, %maroon%, %green%, %navy%, and %purple%.

The basket contains %red% apples, %blue% blueberries, %purple% eggplant, %green% limes, %% and more.

The basket contains apples, blueberries, eggplant, limes, and more.

For colors other than the predefined colors, use the %color=...% WikiStyle. (Note: RGB colors (#rrggbb) should always be specified with lowercase letters to avoid WikiWord conflicts.)

I'd like to have some %color=#ff7f00% tangerines%%,  too!

I'd like to have some tangerines, too!

To change the background color, use %bgcolor=...% as a WikiStyle:

This sentence contains %bgcolor=green yellow% yellow text on a green background.

This sentence contains yellow text on a green background.

See WikiStyle Colors for more color help.

Text justification

WikiStyles are used to control the text justification

%center% This text is centered. 

%right% Right justified.

This text is centered.

Right justified.

and to create floating text:

%rfloat% This text floats to the right

%rframe% floats to the right with a frame

Lorem ipsum dolor sit amet, consectetuer sadipscing elitr

This text floats to the right

floats to the right with a frame

Lorem ipsum dolor sit amet, consectetuer sadipscing elitr

Scope

WikiStyles can also specify a scope; with no scope, the style is applied to any text that follows up to the next WikiStyle specification or the end of the paragraph, whichever comes first. The apply= attribute and its shortcuts allow to change the scope as follows:

apply attributeshortcutstyle applies to...
%apply=img ...%-all images that follow until another style applied
%apply=p ...%%p ...%the current paragraph
%apply=pre ...%-the current preformatted text
%apply=list ...%%list ...%the current list
%apply=item ...%%item ...%the current list item
%apply=div ...%-the current div
%apply=block ...%%block ...%to the current block, whether it's a paragraph, list, list item, heading, or division.

Thus, %p color=blue% is the same as %apply=p color=blue%, and %list ROMAN% is the same as %apply=list list-style=upper-roman%.

Some predefined style shortcuts also make use of apply, thus %right% is a shortcut for %text-align=right apply=block%.

Example: Apply a style to a paragraph:

%p bgcolor=#ffeeee% The WikiStyle specification at the beginning of this line applies to the entire paragraph, even if there are %blue% other WikiStyle specifications %% in the middle of the paragraph.

The WikiStyle specification at the beginning of this line applies to the entire paragraph, even if there are other WikiStyle specifications in the middle of the paragraph.

Caveat: An applied WikiStyle will only take effect if it's on the line that starts the thing it's supposed to modify. In other words, a WikiStyle in the third markup line of a paragraph can't change the attributes of the paragraph:

after the first line of the paragraph,
we try to %apply=p color=blue% change color.
This does't work because the style comes after the first line of the paragraph.

after the first line of the paragraph, we try to change color. This does't work because the style comes after the first line of the paragraph.

However, this %apply=p color=red% paragraph
''will'' be in red because its block style does
occur in the first line of its text.

However, this paragraph will be in red because its block style does occur in the first line of its text.

* Here's a list item
* %list red% Oops, too late to affect the list!
  • Here's a list item
  • Oops, too late to affect the list!

Larger blocks

The >>WikiStyle<< block can be used to apply a WikiStyle to a large block of items. The style is applied until the next >><< is encountered.

>>blue font-style:italic bgcolor=#ffffcc<<
Everything after the above line is styled with blue italic text,

This includes
    preformatted %red%text%%
* lists
-> indented items
>><<

Everything after the above line is styled with blue italic text,

This includes

    preformatted text
  • lists
indented items

Note, the (:div style="..." class="...":) directive does not work the same way as >>WikiStyke<<, it can only contain the regular HTML style and class attributes.

HTML "class" and "style" attributes for tables and divisions

WikiStyles are only the commands between %...% percent signs.

Tables, table directives and (:div:) division blocks allow advanced authors to incorporate the HTML/CSS attributes class= and style=. Note that these attributes are not WikiStyles, knowledge of CSS is required to use them.

(:table style="font-style:italic; color:green; border:1px solid blue; background-color:#ffffcc":)
(:cellnr:)
Everything after the above line is styled with green italic text,

This includes
    preformatted text
* lists
-> indented items
(:tableend:)

Everything after the above line is styled with green italic text,

This includes

    preformatted text
  • lists
indented items

Note, the (:div style="..." class="...":) directive does not work the same way as >>style<<, as mentioned above, it can only contain the HTML style and class attributes.

Custom style shortcuts

The define= attribute can be used to assign a shorthand name to any WikiStyle specification. This shorthand name can then be reused in later WikiStyle specifications.

%define=box block bgcolor=#ddddff border="2px dotted blue"%

%box% [@some sort of text@]

%box font-weight=bold color=green% [@some sort of text@]

some sort of text

some sort of text

Tip: It's often a good idea to put common style definitions into Group Header pages so that they can be shared among multiple pages in a group. Or, the wiki administrator can predefine styles site-wide as a local customization (see Custom WikiStyles).
Tip: Use custom style definitions to associate meanings with text instead of just colors. For example, if warnings are to be displayed as green text, set %define=warn green% and then use %warn% instead of %green% in the document. Then, if you later decide that warnings should be styled differently, it's much easier to change the (one) definition than many occurrences of %green% in the text.
Tip: Any undefined WikiStyle is automatically treated as a request for a class, thus %pre% is the same as saying %class=pre%.

Predefined style shortcuts

PmWiki defines a number of style shortcuts.

  • Text colors: black, white, red, yellow, blue, gray, silver, maroon, green, navy, purple (shortcut for %color=...%)
  • Justification: %center% and %right%
  • Images and boxes
    • Floating left or right: %rfloat% and %lfloat%
    • Framed items: %frame%, %rframe%, and %lframe%
    • Thumbnail sizing: %thumb%
  • Open link in new window: %newwin% (shortcut for %target=_blank%)
  • Comments: %comment% (shortcut for %display=none%)
  • Ordered lists: %decimal%, %roman%, %ROMAN%, %alpha%, %ALPHA% (see also Cookbook:OutlineLists)

Enabling Styles

Styles not listed above can be enabled by a PmWiki Administrator by modifying the local/config.php file. For instance to enable the "line-height" style attribute add the line

$WikiStyleCSS[] = 'line-height';

to the local/config.php file.

Defining scope for other HTML elements

You can add additional HTML elements to $WikiStyleApply to apply WikiStyles to other HTML elements. For example to allow styling on table rows, or anchor tags.

To apply styling to anchor tags, place in config.php:

$WikiStyleApply['link'] = 'a';

Then, you can apply a class or style to an anchor link:

%apply=link red%[[PmWiki.WikiStyles | test link]]

test link

Or, to apply an ID attribute to a table row TR, place in config.php:

$WikiStyleApply['row'] = 'tr';

Then, in an advanced table, you can have:

(:cellnr:) %apply=row id=myid bgcolor=pink% cell content

And also in a simple table:

|| border=1
|| %apply=row id=myrowid% 1 || 2 || 3 || 4 ||

Note, the %apply=row...% WikiStyle should be on the same line as (:cellnr:).

Examples

WikiStyle Examples contains a number of examples of ways to use WikiStyles in pages.

Known Issues

  • Percents in style definitions (like: %block width=50% %) require the use of "pct" instead of "%". PmWiki will convert the "pct" into "%" so that it becomes valid CSS.
  • If you specify multiple values for an attribute, like border="2px solid blue" make sure you place the values in quotes.
  • Be sure to use lowercase letters for red-green-blue hex colors, %color=#aa3333% will work, %color=#AA3333% may not.

See Also


WikiStyleExamples

See also Wiki Styles Plus and Wiki style colors.

PmWiki uses WikiStyles for styling text with color and other attributes. PmWiki 2.0 introduced the ability to control the styling further and to even place styles on blocks.

A style is specified within a pair of %-signs and styles the text that follows, as in:

This text is %color=red% red, %color=blue% blue, %% and normal (black).

This text is red, blue, and normal (black).

There are a wide number of available style properties, borrowed primarily from HTML and CSS. In addition, an author can define a style "shortcut" by using the define= property. For example, to define a style of %red%, one can use:

%define=mystyle color=red%
Here is some %mystyle% red text created using a style shortcut.

Here is some red text created using a style shortcut.

Shortcuts can be combined with other styles, including other shortcuts:

%define=lovelyred color=red%
%define=likegrapefruit bgcolor=yellow%

%red% This text is red, %red bgcolor=#ccc% red on a grey background, and %lovelyred likegrapefruit% red on a yellow background.  

This text is red, red on a grey background, and red on a yellow background.

So far, this is all basically the same as what was available in PmWiki 1.0. PmWiki 2.0 includes the capability to style blocks, by using the apply= style property. Specifying apply=block in a WikiStyle will cause that style to be applied to the entire block, instead of just the text that follows:

This entire block %apply=block bgcolor=yellow% has a yellow background, even though the `WikiStyle appears in the middle of the line.  %bgcolor=pink% Other inline (non-block) WikiStyles can appear in the middle of the line,%% as before.

This entire block has a yellow background, even though the WikiStyle appears in the middle of the line. Other inline (non-block) WikiStyles can appear in the middle of the line, as before.

This means it's now possible to do right-aligned and centered text:

%block text-align=right% The text of this paragraph is right-aligned. 

%block text-align=center% The text of this paragraph is centered.  

The text of this paragraph is right-aligned.

The text of this paragraph is centered.

In fact, PmWiki predefines %right% and %center% style shortcuts so that you can do this more simply:

%right% This is right-aligned.

%center% This is centered.

This is right-aligned.

This is centered.

Authors can define their own custom styles:

%define=Pm block bgcolor=#fdf%
%define=goofy center bgcolor=#dfd border='3px dotted green'%
%define=rediguana right bgcolor=#ffffcc border='1px dotted red' padding=5px%
%define=strike text-decoration=line-through%

%Pm% Any text that is on a light purple background is a comment from "Pm".

%goofy% Here's some text from Goofy.

%rediguana% bla bla by rediguana!

%goofy%Hello, I am %strike%upset%% %strike%disheartened%% happy to meet you.

Any text that is on a light purple background is a comment from "Pm".

Here's some text from Goofy.

bla bla by rediguana!

Hello, I am upset disheartened happy to meet you.

Styles can be applied to almost any kind of block:

* %block bgcolor=yellow% Here is a list item
* Here's another list item

* Here's more of a list

# A new list
  • Here is a list item
  • Here's another list item
  • Here's more of a list
  1. A new list

In particular, this means that outlines are now possible using the predefined %ROMAN%, %roman%, %ALPHA%, and %alpha% list-block styles. The style has to be specified on the first item in the list (and we may develop an alternate syntax for this sort of ordered list):

# %ROMAN% Top level
## %ALPHA% second-level
## second-level
## second-level
### third-level
### third-level
## second-level
### third-level
#### %alpha% fourth-level
##### %roman% fifth-level
##### fifth-level
#### fourth-level
# top-level
# top-level
  1. Top level
    1. second-level
    2. second-level
    3. second-level
      1. third-level
      2. third-level
    4. second-level
      1. third-level
        1. fourth-level
          1. fifth-level
          2. fifth-level
        2. fourth-level
  2. top-level
  3. top-level

Wiki styles can be combined with CSS stylesheets to do this automatically -- see Cookbook:OutlineLists.

Q & A

How do I get a block of preformatted text?

Use something similar to this (assuming you want markup within the block to be interpreted as wiki markup and URIs? to be recognized).

>>white-space=pre<<
This block of text is ''preformatted'', see all   the   white-space
and   linebreaks
are preserved. Links such as [[wiki styles]] etc still work.
>><<

This block of text is preformatted, see all the white-space and linebreaks are preserved. Links such as wiki styles etc still work.

How do I get a block of preformatted text with a colored background and a border?

Use something similar to this (note that wiki markup etc is not recognized within the block):

%block bgcolor=#f0f9ff border='1px solid gray' padding=5px%[@
ip access-list extended example-acl
remark ** This is an example acl **
deny ip any host 10.0.0.1
permit ip any any
@]
ip access-list extended example-acl
remark ** This is an example acl **
deny ip any host 10.0.0.1
permit ip any any

How do I get a block of text (including wiki markup) with a colored background and a border?

>>teal background-color:silver border:'medium dotted green'<<
Hello world
* bullet
# number
>><<

Hello world

  • bullet
  1. number

How do I get a block of text (including wiki markup) with a border that is indented on the left and does NOT extend all the way to right? I'm not interested in having later text to the right as would occur with lfloat...

You can use the indent width=50pct wikistyle.

Before indention...
>>frame indent width=50pct<<
Hello world
* bullet
# number
>><<
... after indention!

Before indention...

Hello world

  • bullet
  1. number

... after indention!


AccessKeys

Access keys (See also Wikipedia:access keys) are keyboard shortcuts for tasks that would otherwise require a mouse click. They are part of markup that may exist on any webpage. On PmWiki steps have been taken to make it easier to use access keys throughout a site, and to make it possible to adjust key assignments to accommodate different languages and preferences.

Using access keys in different operating systems and browsers

Access keys require you to hold down two or more keys.

  • On Windows with Internet Explorer, press ALT + the access key.
  • With Firefox, press SHIFT + ALT + the access key.
  • On a Macintosh with Firefox, Omniweb, Internet Explorer, press Ctrl + the access key.
    • With Safari (Version 4.0.2) press Ctrl + Option + the access key.
  • With Opera press Shift+Esc to enter (or exit) access-key mode.
  • With Konqueror, press Ctrl to enter (or exit) access-key mode.
  • With Chrome, press SHIFT + ALT + the access key

Exceptions exist for specific browsers, and specific versions. For example,

  • Internet Explorer requires that the Enter key be pressed at the end of the sequence for versions 5 and up under Windows, but not under Macintosh (where access keys were not supported until after version 4.5).
  • Firefox versions 1.5 and earlier simply use Alt, while Firefox version 2.0 uses Shift+Alt.

Note, in cases of conflicts between the keyboard shortcuts assigned by browsers and access keys assigned by links and other markup on webpages, many browsers, including Mozilla, Netscape and Internet Explorer, allow access keys to override the browser defaults and require a different sequence to continue using overridden browser assignments (typically, by pressing and releasing the Alt key, instead of holding it down).

Access key assignments in this PmWiki installation

The following is a list of the currently defined access keys for built-in actions. Remember that the letters identified below must be used together with the combination listed above (depending on your operating system and browser). Note that some actions do not have a corresponding access key by default.

Key NameKey ValueFunction
ak_view view
ak_editeedit
ak_historyhhistory
ak_attach attach
ak_print print
ak_backlinks backlinks
ak_logout logout
ak_recentchangescrecent changes
ak_savessave or publish page
ak_saveeditusave and keep editing
ak_savedraftdsave draft
ak_previewppreview page
ak_textedit,jump to edit textarea
ak_em emphasize text
ak_strong strong text

Note: If the 'Key Value' is the same as the 'Key Name', the access key is currently undefined.

When can these access keys be used

  • Access keys ak_view, ak_edit, ak_history, ak_attach, ak_print, ak_backlinks, ak_logout and ak_recentchanges can be used all the time
  • Access keys ak_save, ak_saveedit, ak_savedraft, ak_preview, ak_textedit can only be used in edit mode

Following table explains which button is activated by which access key. Note that the Cancel button has no access key.

Standard Edit modeDraft Edit modeUsed Access Key
SavePublishak_save
 Save draftak_savedraft
Save and editSave draft and editak_saveedit
PreviewPreviewak_preview
  • Access keys ak_em and ak_strong work only in edit mode and when the GUIbuttons? are enabled in local/config.php.

admins (intermediate)

Customizing access keys

PmWiki uses the same "phrase translation" methods for access key mappings as it does for internationalization. This makes it possible for administrators, skins, language translators, and visitors to all influence the way that specific keys are mapped to actions.

See SitePreferences and Site.Preferences for more information and a template.

Note that some skins (e.g., Lean) don't use the translation mechanism. In this case one must edit the template file itself in order to change the access keys.

By convention, the translation phrases for all of the access key actions start with the characters "ak_", so that the page variable "$[ak_edit]" is replaced by the access key for editing as defined by the current preferences, language, skin default, or site default.

Implementation of access keys

Access keys are implemented in html as optional parameters that can be added to links and many other types of markup.

Example: <a href="http://example.com" accesskey="x">Example</a> would create a link to example.com that could be triggered by clicking on the linked word "example" or using the access key Akey+x. That same action key link could be created in PmWiki markup by typing %accesskey="x"%[[http://example.com|Example]]%%, like this: Example. Try it and see if it works. Note that this AKey?+x access key only works this way on this page, because it is simply a shortcut for accessing the link that exists only on this page.

The list of access key assignments in default PmWiki installations generally work throughout a site because links have been created in PmWiki skins and editing screens that incorporate access key parameters using the access key translation phrases. One location where those links can be viewed is Site.PageActions. That page contains the links that the default PmWiki skin, and many other skins, use to generate links such as "View" "Edit" and "History" that appear on most pages (other than editing screens). Each of the links in that page also has an %accesskey=$[ak_xxx]% declaration in front of it, which enables a specific access key for that link.

How can I change the keyboard shortcuts for editing and saving a page?

See Customizing access keys.


PageDirectives

PmWiki uses a number of directives to specify page titles, descriptions, page keywords, and control the display of various components. Keywords are not case sensitive.

(:attachlist:)
Shows a list of attachments of the current group or page, depending on whether attachments are organised per group or per page. The attachlist is displayed at the foot of the uploads page form.
The parameter to (:attachlist:) always resolves to a pagename. The directive then displays all of the attachments currently available for that page.
Options
(:attachlist NAME:) shows a list of attachments of the group or page NAME.
(:attachlist ext=xxx:) specifies an extension for filtering by type of file.
(:attachlist *:) shows the uploads directory and permits browsing of all uploaded files by directory (will not work if $EnableDirectDownload is set to 0).

(:description text:)
Descriptive text associated with the page. (Generates a <meta name='description' content='...' /> element in the page output.)

(:keywords word1, word2, ...:)
Identifies keywords associated with the page. These are not displayed anywhere, but are useful to help search engines locate the page. (Essentially, this generates a <meta name='keywords' content='...' /> element in the output.)

(:linebreaks:), (:nolinebreaks:)
Honors any newlines in the markup; i.e., text entered on separate lines in the markup will appear as separate lines in the output. Use (:nolinebreaks:) to cause text lines to automatically join again.

(:linkwikiwords:), (:nolinkwikiwords:)
Enables/disables WikiWord links in text. Note, this setting requires WikiWords to be enabled, see $EnableWikiWords. See also $LinkWikiWords.

(:markup:) ... (:markupend:) or (:markup:)[=...=]
Can be used for markup examples, showing first the markup and then the result of the markup.
Options
(:markup class=horiz:) will show the markup side by side instead of one upon the other.
(:markup caption='...':) adds a caption to the markup example.
(:markupend:) is not required when using (:markup:) [=...=].
Note that the placement of newlines is very important for this markup. If you are using the [=...=] option then the opening [= MUST occur on the same line as the (:markup:). If you are using the full (:markup:) ... (:markupend:) form then your markup code must appear AFTER a newline after the initial (:markup:).

(:messages:)
Displays messages from PmWiki or recipes, for instance from editing pages.

(:noaction:)
Turns off the section of the skin marked by <!--PageActionFmt?--> thru <!--/PageActionFmt?-->. In the pmwiki skin, this turns off the display of the actions at the top-right of the page (other skins may locate the actions in other locations).

(:nogroupheader:)
(:nogroupfooter:)
Turns off any groupheader or groupfooter for the page. (See GroupHeaders.)

(:noheader:), (:nofooter:)
(:noleft:), (:noright:), (:notitle:)
If supported by the skin, each of these turns off the corresponding portion of the page.

(:redirect PageName:)
Redirects to another wiki page.
(:redirect PageName#anchor:)
Redirects to an anchor within a page
(:redirect PageName status=301 from=name quiet=1:)
Redirects the browser to another page, along with a redirect message. For security reasons this only redirects to other pages within the wiki and does not redirect to external urls. The status= option can be used to return a different HTTP status code as part of the redirect. The from= option limits redirects to occuring only on pages matching the wildcarded name (helpful when (:redirect:) is in another page). The quiet=1 option allows the target page not to display a link back to the original page ($EnableRedirectQuiet variable should be set to 1).

(:spacewikiwords:), (:nospacewikiwords:)
Enables/disables automatic spacing of WikiWords in text.

(:title text:)
Sets a page's title to be something other than the page's name. The title text can contain apostrophes and other special characters. If there are multiple titles in a page, the last one encountered wins (see also $EnablePageTitlePriority about how to change it).

(:nl:)
Creates a new line if there isn't one already there. See this thread for more info.
Similar to [[<<]]

Can I get (:redirect:) to return a "moved permanently" (HTTP 301) status code?

Use (:redirect PageName status=301:).

Is there any way to prevent the "redirected from" message from showing at the top of the target page when I use (:redirect:)?

From version 2.2.1 on, set in config.php $EnableRedirectQuiet=1; and in the page (:redirect OtherPage quiet=1:) for a quiet redirect.

Is there any method for redirecting to the equivalent page in a different group, i.e. from BadGroup?/thispage => GoodGroup?/thispage using similar markup to (:redirect Goodgroup.{Name}:)?

(:redirect Goodgroup.{$Name}:) works if you want to put it in one page.
If you want it to work for the entire group, put (:redirect Goodgroup.{*$Name}:) into Badgroup.GroupHeader? - however, that only works with pages that really exist in Goodgroup; if you visit a page in Badgroup without a corresponding page of the same name in Goodgroup, instead of being redirected to a nonexistant page, you get the redirect Directive at the top of the page.
With (:if exists Goodgroup.{*$Name}:)(:redirect Goodgroup.{*$Name}:)(:ifend:) in Badgroup.GroupHeader? you get redirected to Goodgroup.Name if it exists, otherwise you get Badgroup.Name without the bit of code displayed.

How can a wiki enable linebreaks by default, i.e. without having the directive (:linebreaks:) in a page or in a GroupHeader?

Add to config.php such a line:
$HTMLPNewline = '<br/>';


IncludeOtherPages

The (:include:) directive makes it possible to insert (or "transclude") the contents of other pages into the current wiki page. All of the include directives below perform a straight text inclusion. In particular, any page links in the included text are assumed to link to pages in the current group if not otherwise qualified.

Syntax

The basic syntax is

with pagename includes the full page from the same group.
includes a named variable from a page, Group and PageName are options

The full syntax is

includes a page according to the parameters supplied. Parameters are optional.

Parameters

The directive can have multiple Name parameters with or without anchors, and multiple template variable parameters.

Named pages

(:include PageName:)
(:include Group.PageName:)
(:include Page1 Page2 Group1.Page3 Group2.Page4:)
Includes the entire text of another page into the current page. Multiple pages may be specified, but only the first available is included.

You can use the above feature to display an error message if an include fails. Create a page, eg. Site.IncludeFailed containing the error message. You can use any page name. Then, in your include markup, append this page at the end of the page list:

 (:include Page1 Page2 Page3 Site.IncludeFailed:)

A slightly more complex approach is outlined at the talk page.

#From#To anchors

(:include PageName#from#to:)include lines from PageName between the [[#from]] and [[#to]] anchors
(:include PageName#from#:)include all lines after [[#from]] to the end of the page
(:include PageName##to:)include all lines from the start of the page to [[#to]]
(:include PageName#from:)include everything between [[#from]] and the next anchor
(:include PageName#:)include everything from the top of the page to the first anchor
Note: do not put whitespace between "#from" "#to"
Note: text on the same line as a closing anchor but preceding the closing anchor will NOT be included in the text. Example Below:
[[#start]]some text on the first line
some text on the last line [[#end]]
The above, when included via (:include PageName#start:) will have the text on the first line but not the text on the last line.
(:include Page1 Page2 #from#to:)
Include from the first available of Page1, Page2 between the [[#from]] and [[#to]]
Note: put whitespace between "Page2" and "#from#to". The same anchors "#from#to" should be in both pages. If proper anchors are missing in the first available of Page1, Page2 the whole contents of the page is included.
This does not seem to work in 2.2 betas. See Cookbook:IncludeSection for a fix.
(:include Page1#from1#to1 Page2#from2#to2:)
Include the first from the first available of Page1 (between the [[#from1]] and [[#to1]]) or Page2 (between the [[#from2]] and [[#to2]] )
Note: Previous versions of PmWiki allowed whitespace between #from and #to anchors even though it was not designed to. Newer versions do not allow whitespace anymore. To re-enable this "exploited misbehavior" put this into your config.php or farmconfig.php
Markup('includeanchors', '<include', '/(\\(:include.*?#\\w+)\\s+(#\\w+)/', '$1$2');

Lines=from..to

(:include PageName lines=10:)
(:include PageName lines=5..10:)
(:include PageName lines=5..:)
Include the first 10 lines, lines 5-10, or lines 5 and up from PageName. A "line" in this context refers to a line of source. Thus a line may be a paragraph that wraps over several lines on the screen, or a completely blank line.
(:include Page1 Page2 Page3 lines=1..5:)
Include the first five lines from the first available of Page1, Page2, or Page3. (To include lines from a list of pages, use a separate include for each.)

Self=

(:include PageName self=0:)
The parameter self can be 0 or 1. It tells the include directive if it is allowed to include the current page. This is useful if PageName is a variable like {$Name} and you want to prevent the directive from including the current page.

Page text variables

{Group/PageName$:Var}
Includes definition list values from an (optional) page as page text variables. These are defined using a definition list (:item:description), simple colon delimiter (item:description), or special markup ((:item:description:)).

Basepage=

(:include PageName basepage=BasePageName:)
Include PageName, but treat all relative links and page variables on PageName` as relative to BasePageName?.

If basepage= is provided all relative links and page variables are interpreted relative to basepage. So, if one creates TemplateName as

Name: {$:Name}
Address: {$:Address}

then the directive

(:include TemplateName basepage=PageName:)

will retrieve the contents of TemplateName, treating any page variables and links as being relative to PageName. In particular, the values for {$:Name} and {$:Address} will be taken from PageName, but things like {$Title} and {$LastModifiedBy} would also work here.

Basepage usage

The primary purpose of basepage is to allow the include of pages in a way that mimics the 2.1.x behavior where page variables and links are interpreted relative to the currently displayed page. This is done with:

(:include SomeOtherPage basepage='' :)
  -or-
(:include SomeOtherPage basepage={*$FullName} :)

It also allows GroupHeader and GroupFooter to have their page variables and links be relative to the currently displayed page (instead of GroupHeader and GroupFooter):

  ## PmWiki default $GroupHeaderFmt setting
  $GroupHeaderFmt = 
    '(:include {$Group}.GroupHeader self=0 basepage={*$FullName}:)(:nl:)';

Otherwise, using IncludeAll inside of a GroupHeader would display 'GroupHeader' and not the name of the currently displayed page.

The basepage= parameter is general enough that it can also be used as a templating engine, so that we can grab a template page containing variables that are then filled in with values from another page:

(:include TemplatePage basepage=DataPage :)

And, of course, a single TemplatePage? can actually contain multiple templates delimited by anchors, so that we end up with a syntax eerily similar[5] to pagelist-templates:

    (:include TemplatePage#abc basepage=DataPage :)

So then TemplatePage can use a syntax like:

    
    [[#abc]]
    ...template stuff here...
    [[#abcend]]

and it's possible to display TemplatePage as a template without it being interpreted... same as we do for Site.PageListTemplates.

[1]Okay, maybe it's not so eerie, given that the pagelist template code actually uses the same function as (:include:) to grab its templates. But it's still a useful parallel.

Specifying variables as parameters

You can also specify variable values inline with the include statement, and refer to the variables in the template using the {$$variable1} format:

(:include TemplatePage variable1="value" variable2="value2":)

This assumes that a site has $EnableRelativePageVars enabled, which is recommended in PmWiki 2.2.0 -- but was disabled by default in version 2.2.8 and earlier.

For example, on my included page ("template") I might have this:

[[#ivars]]
Hi, {$$Name}, how are you today?
[[#ivarsend]]

Hi, {$$Name}, how are you today?

Then, including that section above (that section is available via the section {$FullName}#ivars)) you get this type of behavior:

(:include {$FullName}#ivars Name=Sam:)

Hi, Sam, how are you today?

If a value contains spaces, quote it:

(:include {$FullName}#ivars Name="my friend":)

Hi, my friend, how are you today?

See also $EnableUndefinedTemplateVars.

See Also

Styling Note

By default, Included pages or lines cannot be distinguished from other text on the page. To provide a visual indication that this text is special, you can apply Wiki Styles. For example:

%define=leftborder border-left="2px solid #88f" margin-left="2px" padding="1px 0 3px 10px"%
What is PmWiki?
>>leftborder<< (:include PmWiki.PmWiki lines=1..4:) 
>><<
''Have a very nice day!''

What is PmWiki?

PmWiki is a wiki-based content-management system (CMS) for collaborative creation and maintenance of websites.

PmWiki pages look and act like normal web pages, except they have an "Edit" link that makes it easy to modify existing pages and add new pages into the website, using basic editing rules. You do not need to know or use any HTML or CSS. Page editing can be left open to the public or restricted to small groups of authors.

Have a very nice day!

Parameter References

Any parameters supplied to an include statement (whether they are keywords or not) are accessible inside the included page as a special {$$...} variable of the same name. This feature can be used to provide extra information to use when displaying the included page.

Notes

  • You can also say (:include My/Page#myanchor lines=4:) which starts from, and includes, the line with the anchor [[#myanchor]] for four lines.

Notes about use with conditional markup

The (:include ...:) markup is processed after conditional markup is evaluated.
Therefor you can include a page or page section as part of a condition, like

(:if some condition:)(:include SomePage#section:)(:if:)

But (:include SomePage#section:) doesn't look to see if [[#section]] is part of a conditional, like

(:if some condition:)[[#section]]...[[#sectionend]](:ifend:)

(:include SomePage#section:) will ignore such a condition.

When testing variables in included pages the context of the page (source or target) can be useful. See special references for details.


What's the maximum number of includes that can exist in a page?

My site seems to stop including after 48 includes. ($MaxIncludes)

By default, PmWiki places a limit of 50 include directives for any given page, to prevent runaway infinite loops and other situations that might eat up server resources. (Two of these are GroupHeader and GroupFooter.) The limit can be modified by the wiki administrator via the $MaxIncludes variable.

Is there any way to include from a group of pages without specifying by exact name, e.g. between Anchor X and Y from all pages named IFClass?-* ?

This can be achieved using page lists.

There appears to be a viewing issue when the included page contains the (:title:) directive.

In a default installation, the last title in the page overrides previous ones so you can place your (:title :) directive at the bottom of the page, after any includes. See also $EnablePageTitlePriority.


InterMap

The InterMap (also called InterWiki? in some other wikis) is a system for defining links between WikiWikiWeb sites that was first developed by UseMod? and Meatball (see UseMod:InterWiki and Meatball:InterWiki). The method is to use a word shortcut that stands for a defined path. InterMap links have the form MapPrefix:PagePath, where the host prefix is converted to a partial URL based on entries in the site's intermap.txt and localmap.txt files.

The default intermap.txt

The default intermap.txt distributed with PmWiki (in the scripts/ directory) includes the following InterMap entries:

The page Site.InterMap

Site.InterMap includes the following entries:

Thus, "PmWiki:Variables" becomes "http://www.pmwiki.org/wiki/PmWiki/" + "Variables," a link to the PmWiki.Variables page on the official PmWiki web site, Wiki:FrontPage is a link to the front page of the first WikiWikiWeb, and Wikipedia:Stonehenge takes you to the Wikipedia article about the famous megaliths in England.

Usage in a wiki page

Like other links, you can use the double-bracket syntax to get different link text:

* [[Meatball:StartingPoints | starting points]] over at Meatball
* [[starting points -> Meatball:StartingPoints]] over at Meatball

If you want to link just to what the intermap says (e.g. http://www.wikipedia.com/wiki/ for Wikipedia), then do [[Wikipedia:. | Wikipedia's main page]], which produces Wikipedia's main page. Note the . (period) after the Map: reference.

The special Path: InterMap entry can be used to create "relative urls" in links.

Custom InterMap prefixes

The actual set of InterMap links at any site is defined by the site administrator via the Site.InterMap page and the local/localmap.txt file.

An intermap entry takes the following format:

MapPrefix:      http://example.com/partial/url/

The InterMap entry can be for any of the link schemes supported by PmWiki.
You can create your own InterMap links by doing one or more of the following:

  • Modify the page called Site.InterMap and place entries like the ones above in it.
  • Create a file called local/localmap.txt and place entries like the ones above in it.
  • In a WikiFarm installation you can create a file called local/farmmap.txt and there place entries like the ones above in it. These prefixes will be common to all the wikis in the farm.
  • Ensure that there is a space after the colon.

Do not edit the file scripts/intermap.txt directly! If you do, you'll lose your changes when you upgrade PmWiki.

Variables and InterMap links

It's possible to use variables within your InterMap entries. The following entries create ThisWiki: and ThisPage: shortcuts:

ThisWiki:        $ScriptUrl
ThisPage:        {$PageUrl}

You can also define InterMap entries where the text of the entry is substituted into the middle of the URL. Just include '$1' in the URL where you want the substitution to take place. For example:

Jargon: http://catb.org/~esr/jargon/html/$1.html

would cause Jargon:F/feature-creep to be converted to http://catb.org/~esr/jargon/html/F/feature-creep.html.

Tips and tricks

It is possible to document your intermap prefixes directly in the page Site.InterMap. The extra text will not cause a performance penalty, nor will it break the definition of prefixes. However, be aware that anything matching a line starting with a word and a colon (:) will be considered to define a prefix.

The order in which various sources are checked for definitions of prefixes is controlled by the variable $InterMapFiles. Currently the precedence (highest to lowest is as follows):

Are InterMap names case sensitive?

Yes, thus eAdmin: is a different InterMap link than EAdmin:.

How can I achieve a localmap.txt mapping with the effect of Pics: Path:/somepathto/pics/?

Use the following:

Pics: /somepathto/pics/

How can I define an InterMap in PHP?

Use the following:

      $LinkFunctions['PmWikiHome:'] = 'LinkIMap';
      $IMap['PmWikiHome:'] = 'http://pmwiki.org/wiki/$1';

ConditionalMarkup

Using the (:if:) Directive

The (:if:) directive allows portions of a page to be included or excluded from rendering. The generic forms of the (:if:) directive are

(:if cond param:) body (:ifend:)
(:if cond param:) body (:else:) body (:ifend:)
(:if cond param:) body (:elseif cond param:) body (:ifend:)

where "cond" names a condition to be tested, and "param" is a parameter or other argument to the condition.

Note that (:if:) without parameters and (:ifend:) are identical. Also note that (:if cond:) automatically closes a previous conditional. For nested multiple levels, see Nested conditionals.

Built-in Conditions

The built-in conditions include:

(:if name PAGENAME:)  -  current page is named "PAGENAME"
(:if group GROUPNAME:)  -  current group is named "GROUPNAME"
(:if auth LEVEL PAGENAME:)  -  viewer is authorized - meaning "what they are allowed to do" - matches a "LEVEL" where LEVEL can be: read, edit, upload, attr or admin; PAGENAME is optional.
(:if authid:)  -  current viewer is authenticated - meaning they have proven who they are via login - to use this the wiki must include recipe AuthUser or others which set the $AuthId variable.
(:if enabled InvalidLogin:)  -  username and password not authenticated. To use this the wiki must include recipe AuthUser.
(:if true:)  -  always include text
(:if false:)  -  always exclude text (same as a comment)
(:if attachments:)  -  current page has one or more attachments

If used in a sidebar, header, or footer the condition applies to the main page.

(:if date DATE VALUE:)  -  DATE may be year-month. year-month-day is optional.

Evaluates to true if VALUE is within DATE ("now" or "today" is assumed if VALUE is omitted, as in the following examples.) (Note that VALUE can be a recognizable date via strtotime() whereas DATE [or DATE1? and DATE2? below] have a more fixed format which explicitly must exclude spaces. Any spaces in DATE1? or DATE2? cause unpredictable results.)

(:if date DATE.. VALUE:)  -  true if VALUE (or current date if omitted) is DATE or later (unlimited)
(:if date ..DATE VALUE:)  -  true if VALUE (or current date if omitted) is DATE or earlier (unlimited)
(:if date DATE1..DATE2 VALUE:)  -  true if VALUE (or current date if omitted) is in range DATE1 to DATE2 (inclusive)

dates are in standard format yyyy-mm-dd or yyyymmdd or yyyymmddThhmm (note the "T" between the date and the hour, and also see comment above on format of VALUE).
Note the ".." cannot have leading or trailing spaces.

(:if enabled VAR:)  -  true if PHP VAR is true
(:if enabled AuthPw:)  -  true if user has entered any password during the current browser session.

- This does not mean the user has entered the correct password, just that they entered one.

(:if equal STRING1 STRING2:)  -  true if STRING1 equals STRING2, use quotes if the string or string variable contains spaces, eg "MY STRING"
(:if match REG_EXPRESSION:)  -  true if current page name matches the regular expression
(:if exists PAGENAME:)  -  true if the page pagename exists
(:if ontrail WikiTrailPage ThisPage:)  -  true if ThisPage? is in a list used as a trail on WikiTrailPage?

The name and group conditionals will work even for an included page, as the "name" and "group" conditionals always check the currently displayed page, as opposed to the page that the markup appears in.

Note: Although there is no built-in conditional markup to test ?action=, you can use (:if equal {$Action} ACTION:) to test what the current action being requested is.

Negated Conditions

Negated forms of conditions also work:

(:if !attachments:)  -  this page has no attachments
 
(:if ! name PAGENAME:) current page is NOT named "PAGENAME"
(:if name -PAGENAME :)

Nesting Conditions

Note that (:if cond:) automatically closes a previous conditional. Thus, the following two examples have identical meaning:

  • (:if cond1:) cond1 is true (:if cond2:) cond2 is true (:ifend:)
  • (:if cond1:) cond1 is true (:ifend:)(:if cond2:) cond2 is true (:ifend:)

Conditions can be nested from 2.2.beta 66. To have nested conditionals you need to number the if, and the matching else/ifend:

(:if cond1:)
  cond1 is true
  (:if2 cond2:)
     cond1 and cond2 are true
  (:else2:)
     cond1 is true, cond2 is not
  (:if2end:)
(:else:)
  cond1 is false, cond2 testing was ignored
(:ifend:)

Spaces were added for better readability.

Using wildcard placeholders

The character * can be used as a wildcard to represent any character, zero, one, or multiple times.
The character ? can be used as a wildcard to represent any character exactly once.
Wildcard characters (* and ?) can be used with the name and group conditional markups, thus:

(:if name PmCal.2005* :)  -  current page is in group PmCal and begins with 2005
(:if group PmWiki* :)  -  current page is in group PmWiki or a group beginning with PmWiki
(:if name Profiles.*,-Profiles.Profiles :)  -  current page is in group Profiles but not Profiles.Profiles

Using page text variables, page variables and markup expressions

Page text variables (PTVs?), page variables (PVs?) and markup expressions can be used in conditional markup. They will be assigned/evaluated before the condition(s).

Combining conditions

Conditions (as previously defined) may be combined into more complex conditional expressions using one of these three equivalent forms:

(:if expr EXPRESSION :)
(:if [ EXPRESSION ] :)
(:if ( EXPRESSION ) :)

Conditions are combined into expressions with boolean operators and brackets. In the next table, A and B are either regular conditions or (round-)bracketed sub-expressions of regular conditions:

ExpressionOperatorResult
A and BAndTRUE if both A and B are TRUE.
A or BOrTRUE if either A or B is TRUE.
A xor BXorTRUE if either A or B is TRUE, but not both.
! ANotTRUE if A is not TRUE.
A && BAndTRUE if both A and B are TRUE.
A || BOrTRUE if either A or B is TRUE.

Example

(:if [ name SomePage and group SomeGroup ]:)    equivalent to (:if name SomeGroup.SomePage:)

Important Notes:

  • Spaces are required around operators and brackets.
  • No specific feedback is given for syntax errors or unbalanced brackets.
  • Use round brackets (not square) for nested expressions.

Thus, the following is a valid way of building an expression that shows the following contents only when the user is either the administrator, or is logged in and the time is later than the given date:

(:if [ auth admin || ( authid && date 2006-06-01.. ) ] :)

Nesting with square brackets will silently fail to work as expected:

(:if [ auth admin || [ authid && date 2006-06-01 ] ] :)    NOTE: Doesn't Work!

A common use of these complex tests are for expressions like:

(:if expr auth admin || auth attr || auth edit :)
[[Logout -> {$Name}?action=logout]]
(:ifend:)

which provides a logout link only when the browser has admin, attr, or edit permissions.

admins (advanced)

Creating new conditions

See Cookbook:ConditionalMarkupSamples.

See also special references for the use of {*$Variables}.


Page specific variables

This page describes the "variables" that are associated with pages. Page variables have the form {$variable}, and can be used in page markup or in certain formatting strings in PmWiki. For example, the markup "{$Group}" renders in this page as "Test".

Note: Do not confuse these variables (set and used only in PmWiki pages) with PHP variables. Page variables can be read in PHP with the PageVar() function.

Note that these variables do not necessarily exist in the PHP code, because they have to be determined for a specific page. (However, they are usable in FmtPageName strings.)

There is also the form {pagename$variable}, which returns the value of the variable for another page. For example, "{MarkupMasterIndex$Title}" displays as "Markup Master Index".

Special references

Special referenced variables are used to specify the context of the variable when:

  • the variable is included into a destination (target) page
  • the variable is used in a sidebar, header, or footer

Prefixing the variable name with an asterisk (*) means the variable's value is related to the target page or main (body) page.

  • {*$PageVariablename?} - prefixed by an asterisk (*) - value reflects target page context

Without the asterisk the variable's value is that in the page from which it originates, eg source page of include, sidebar, or header or footer.

Special references are also used in page text variables and page list templates.

For example you can test to see if the page is part of another page

(:if ! name {$FullName}:) 
%comment% name of this page is not the same as the page this text was sourced from
->[[{$FullName}#anchor | more ...]]
(:ifend:)

or refer to the main page in a sidebar, footer, or header

This page is [[{*$FullName}]]

This page is Test.IncludeAll

Default page variables

The page variables defined for PmWiki are:

{$Action} - page's url action argument, as in "browse"
{$BaseName} - page's "base" form (stripping any prefixes or suffixes defined via $BaseNamePatterns) as in "Test.IncludeAll"
{$DefaultGroup} - default group name, as in "PmWiki"
{$DefaultName} - name of default page, as in "HomePage"
{$Description} - page's description from the (:description:) markup, as in ""
{$FullName} - page's full name, as in "Test.IncludeAll"
{$Group} - page's group name, as in "`Test"
{$Groupspaced} - spaced group name, as in "Test"
{$LastModified} - date page was edited, as in "December 16, 2023, at 08:21 PM"
{$LastModifiedBy} - page's last editor, as in "simon"
{$LastModifiedHost} - IP of page's last editor, as in "203.118.185.95"
{$LastModifiedSummary} - Summary from last edit, as in "change redirected link (nb highlight struggles on this page when searching it) (-1)"
{$LastModifiedTime} - time page was edited in unix-style timestamp, as in "1702758077"
This can be used (preceded by '@') in {(ftime)} and other date/time markups.
{$Name} - page name, as in "IncludeAll"
{$Namespaced} - spaced page name, as in "Include All"
{$PageUrl} - page's url, as in "$ScriptUrl/IncludeAll"
{$PasswdRead} - "read" permissions for the page e.g. ""
{$PasswdEdit} - "edit" permissions for the page e.g. ""
{$PasswdAttr} - "attr" permissions for the page e.g. "(set by group) ****"
{$RequestedPage} - page requested in URL, used on Site.PageNotFound. e.g. "IncludeAll"
{$SiteGroup} - default group name for e.g. RecentChanges, as in "Site"
{$Title} - page title (may differ from Name), as in "All pages of the documentation"
{$Titlespaced} - either the page title (if defined), or the spaced page name, as in "All pages of the documentation"

In addition to the above, there are some page-invariant variables available through this markup:

{$Author} - the name of the person currently interacting with the site, as in ""
{$AuthId} - current authenticated id, as in "" note the lower case 'd'.
{$Version} - PmWiki version, as in "pmwiki-2.3.38"
{$VersionNum} - The internal version number, as in "2003038"
{$ScriptUrl} - The url to the pmwiki script, as in "https://www.pmwiki.org/wiki"

Page variable security ($authpage)

The form {pagename$variable} or some PageLists, can display the values for other pages, regardless of the password protections.

If the other pages are protected and the visitor has no read permissions, PageVariables, unlike PageTextVariables, normally display the values. While most variables do not contain sensitive information, some of them could do: $Title, $Description and those starting with $LastModified.

Administrators and module developers can redefine the sensitive page variables to respect authentications, by using the "$authpage" variable instead of "$page" in the definition. The following snippet can be added in local/config.php -- it will rewrite the default possibly sensitive definitions to the secure ones.

foreach($FmtPV as $k=>$v) {
  if(preg_match('/^\\$(Title(spaced)?|LastModified(By|Host|Summary|Time)?|Description)$/', $k))
    $FmtPV[$k] = str_replace('$page', '$authpage', $v);
}

Custom page variables

You may add custom page variables as a local customization. In a local configuration file or a recipe script, use the variable $FmtPV:

$FmtPV['$VarName'] = "'variable definition'";
$FmtPV['$CurrentSkin'] = '$GLOBALS["Skin"]';
$FmtPV['$WikiTitle'] = '$GLOBALS["WikiTitle"]';

Defines new Page Variable of name $CurrentSkin, which can be used in the page with {$CurrentSkin} (also for Conditional markup). It's necessary to use the single quotes nested inside double-quotes as shown above (preferred) or a double-quoted string nested inside single-quotes like '"this"'.

If you want to have a Page Variable that returns the currently used password (more precisely, the last password entered), you can use

$FmtPV['$AuthPw'] = 'reset(array_keys((array)@$_SESSION["authpw"]))';

See also

Is there a variable like $LastModified, but which shows me the creation time?

No, but you can create one in config.php. For instance:

# add page variable {$PageCreationDate} in format yyyy-mm-dd
$FmtPV['$PageCreationDate'] = 'strftime("%Y-%m-%d", $page["ctime"])';

If you like the same format that you define in config.php with $TimeFmt use

 $FmtPV['$Created'] = "strftime(\$GLOBALS['TimeFmt'], \$page['ctime'])";

How can I test if a variable is set and/or not empty?

Use (:if ! equal "{$Variable}" "":) $Variable is not empty. (:ifend:). Note that undefined/inexistent variables appear as empty ones.


PageTextVariables

Page text variables are string variables created in the wiki text of a page, and can be automatically made available for inclusion in other pages.

Defining Page Text Variables

There are three ways to define automated Page Text Variables:

  • use a definition list - the normal pmwiki markup for a definition list will create a page text variable
Example definition list:
:Name: Crisses
"{$:Name}"
Name
Crisses

"Crisses"

This creates a new variable that can be accessed by {$:Name} (becomes: "Crisses") in the page.
  • use a simple colon delimiter in normal text
Example colon delimited:
Address: 1313 Mockingbird Lane

"{$:Address}"

Address: 1313 Mockingbird Lane

"1313 Mockingbird Lane"

This creates the {$:Address} variable (variable markup becomes: "1313 Mockingbird Lane") in the page.
  • hidden directive form - PmWiki markup that doesn't render on the page, but defines the variable
Example directive:
(:Country: Transylvania :)
"{$:Country}"

"Transylvania "

This creates the {$:Country} variable (variable markup becomes: "Transylvania ") in the page.

Usage

Usage on the same page

On the same page you can resolve page text variables through the {$:Var} format (shown above).

Usage in headers and footers: special references

If you want a GroupHeader, GroupFooter, SideBar, etc to call on page text variable in the main page, you need to include special reference information. To explicitly reference the page text variable from the page being displayed add an asterisk to the page text variable's markup: {*$:Address} on the GroupFooter or GroupHeader page.

Example
{*$:City}

To include a page text variable from a header or footer see usage from other pages below.

Special references also apply to page variables and page list templates.

Usage from other pages

If you want to pull the data from another page, use the {Group/PageName$:Var} format.

Example:
Suburb: Khandallah
(:Lake:Taupo:)
:Mountain:Mt Ruapehu

->"{PmWiki/PageTextVariables$:Suburb}"
->"{{$FullName}$:Lake}"
->"{PmWiki/PageTextVariables$:Mountain}"

Suburb: Khandallah

Mountain
Mt Ruapehu
"Khandallah"
"Taupo"
"Mt Ruapehu"

Usage from included pages

Page text variables are never included from their source page. See Usage from other pages above to refer to a page text variable on another page.

Usage with pagelists

Page lists can also access the page text variables:

Example:
(:pagelist group=PmWiki order=$:Summary count=6 fmt=#singleline:)

And to create pagelist formats (such as those documented at Site.Page List Templates, Page Lists, Page List Templates, Page Variables. Store custom pagelists at Site.Local Templates).

Page lists can also use page text variables to select pages :

Example:
(:pagelist group=PmWiki $:City=Paris count=8 fmt=#singleline order=-name:)
lists pages having '$:City' set to 'Paris'.
Example: multiple selections with spaces
(:pagelist group=PmWiki $:City="Addis Ababa,Paris" order=-$:Version count=8 fmt=#singleline:)
'quotes' must surround all the selections.
  • When using page text variables for selection or ordering, don't put the curly braces around the variable name. The curly forms do a replacement before the pagelist command is evaluated.

Testing if set or not set

=-PTV is set (is not empty), eg (:pagelist $:Var=- :)
=-?*PTV is not set (is empty), ie not one character followed by 0 or more characters, eg. (:pagelist $:Var=-?* :)
=*display all pages, regardless of the page text variable (slow)
=-*display no pages, regardless of the page text variable (slow)

Tip : (:if ! equal "{$:PTV}" "":) will test if PTV is empty/unset or not.

Example: Pages without a summary
(:pagelist group=PmWiki $:Summary=-?* count=6  fmt=#singleline:)

Use page text variable in a template

Display pages by Audience page text variable.

Example:
>>comment<<
[[#byaudience]]
(:if ! equal '{=$:Audience}' '{<$:Audience}':)
-<'''{=$:Audience}''':  
(:ifend:)
[[{=$Name}]]
[[#byaudienceend]]
>><<
(:pagelist group=PmWiki count=10 fmt=#byaudience order=-$:Audience:)

{=$:Audience}:

{=$Name}?

visitors (intermediate) :

WebFeeds AccessKeys

readers, authors (basic):

DocumentationGuidelines

readers :

WikiElements

Developers:

UpdatePage

authors, admins (intermediate) :

PageLists

authors, admins (advanced) :

ConditionalMarkup

authors (intermediate) :

MarkupCharacters TableDirectives PageVariables

Use page text variables in conditional markup

Page text variables will be assigned/evaluated before any conditional markup is evaluated. This effectively means that you cannot declare a PTV within an if...else condition; and also that a PTV will have a value even if it is set within a (:if false:)....(:if:) condition.

Usage - from within code (developers only)

The standard PageVar?($pagename,$varname) function can return page text variables, but remember to include the dollar and colon like this:

$var=PageVar?($pagename,'$:City')

It works by caching all page (text) variables it finds in a page (in $PCache) and returns the one requested.


MarkupExpressions

The {(...)} "expression markup" allows for a variety of string and formatting operations to be performed from within markup. Operations defined by this recipe include substr, ftime, strlen, rand, toupper / tolower, ucfirst, ucwords, pagename and asspaced.

substr

The "substr" expression extracts portions of a string. The arguments are

  1. the string to be processed. Always quote the string to be processed.
  2. the initial position of the substring. Note that the initial position argument is zero-based (i.e., the first character is referenced via a "0").
  3. the number of characters to extract
 {(substr "PmWiki" 2 3)}
 {(substr "PmWiki" 2)}
 {(substr "PmWiki" 0 1)}
 {(substr "PmWiki" 0 -3)}
 {(substr "PmWiki" -3)}
 Wik
 Wiki
 P
 PmW?
 iki

To obtain the last n characters of a string use {(substr "string" -n)}
To truncate the last n characters of a string use (substr "string" 0 -n)}

ftime

"Ftime" expressions are used for date and time formatting. The generic form is

{(ftime "fmt" "when")}
{(ftime fmt="fmt" when="when")}

where fmt is a formatting string and when is the time to be formatted. The arguments can be in either order and may use the optional "fmt=" and "when=" labels.

Examples:

 {(ftime)}
 {(ftime fmt="%F %H:%M")}
 {(ftime %Y)}
 {(ftime fmt=%T)}
 {(ftime when=tomorrow)}
 {(ftime fmt="%Y-%m-%d" yesterday)}
 {(ftime "+1 week" %F)}
 {(ftime fmt=%D "+1 month")}
 {(ftime fmt="%a%e %b" when="next week")}
 November 10, 2024, at 01:30 AM
 2024-11-10 01:30
 2024
 01:30:25
 November 11, 2024, at 12:00 AM
 2024-11-09
 2024-11-17
 12/10/24
 Mon11 Nov

The fmt parameter is whatever is given by "fmt=", the first parameter containing a '%', or else the site's default. The formatting codes are described at http://php.net/strftime. In addition to those, '%F' produces ISO-8601 dates, and '%s' produces Unix timestamps. Some common formatting strings:

     %F                # ISO-8601 dates      "2024-11-10"
     %s                # Unix timestamp      "1731202225"
     %H:%M:%S          # time as hh:mm:ss    "01:30:25"
     %m/%d/%Y          # date as mm/dd/yyyy  "11/10/2024"
     "%A, %B %d, %Y"   # in words            "Sunday, November 10, 2024"

The when parameter understands many different date formats. The when parameter is whatever is given by "when=", or whatever parameter remains after determining the format parameter. Some examples:

    2007-04-11            # ISO-8601 dates
    20070411              # dates without hyphens, slashes, or dots
    2007-03               # months
    @1176304315           # Unix timestamps (seconds since 1-Jan-1970 00:00 UTC)
    now                   # the current time
    today                 # today @ 00:00:00
    yesterday             # yesterday @ 00:00:00
    "next Monday"         # relative dates
    "last Thursday"       # relative dates
    "-3 days"             # three days ago
    "+2 weeks"            # two weeks from now

Note: If you want to convert a Unix timestamp you must prefix with the @. Thus, "{(ftime "%A, %B %d, %Y" @1231116927)}".

The when parameter uses PHP's strtotime function to convert date strings according to the GNU date input formats; as of this writing it only understands English phrases in date specifications.

The variable $FTimeFmt can be used to override the default date format used by the "ftime" function. The default $FTimeFmt is $TimeFmt.

strlen

The "strlen" expression returns the length of a string. The first argument is the string to be measured.

 {(strlen "{$:Summary}")}
 0

rand

The "rand" expression returns a random integer. The first argument is the minimum number to be returned and the second argument is the maximum number to be returned. If called without the optional min, max arguments rand() returns a pseudo-random integer between 0 and RAND_MAX. If you want a random number between 5 and 15 (inclusive), for example, use (rand 5 15).

 {(rand)}
 {(rand 1 99)}
 955165679
 9

toupper / tolower

The "toupper" and "tolower" expressions convert a string into uppercase or lowercase. The first argument is the string to be processed.

 {(toupper "{$:Summary}")}
 {(tolower "{$:Summary}")}

ucfirst / ucwords

The "ucfirst" expression converts to uppercase the first character of the string, and "ucwords", the first character of each word. The first argument is the string to be processed.

 {(ucfirst "{$:Summary}")}
 {(ucwords "{$:Summary}")}

pagename

The "pagename" expression builds a pagename from a string. The first argument is the string to be processed.

 {(pagename "{$:Summary}")}
 Test.

asspaced

The "asspaced" expression formats wikiwords. The first argument is the string to be processed.

 {(asspaced "{$FullName}")}
 Test.Include All

Nesting expressions

Markup expressions can be nested:

 {(tolower (substr "Hello World" 2))}
 llo world

Notes

  • For PmWikis? version 2.2.33 or older, the string-processing expressions may not work properly on multibyte UTF-8 characters. Newer versions should work fine.

See also


Forms

This page explains how you can embed input forms into wiki pages.

Input forms don't actually handle processing of the form data -- the feature simply allows creation of forms inside wiki pages. Forms processing can be found in the Cookbook (see below).

Markup

Two directives are used to begin and end forms:

    (:input form "url" method:)
    ...
    (:input end:)

The (:input form:) directive starts a form that will post to url (optional action=url) using the supplied method (optional method=method). The url must be in quotes if not specified via action=. If the url is omitted, then the current page is assumed. If method is omitted then "POST" is assumed. An optional name="FormName" argument can be used to name the form. You can explicitly state action=url or method=get or you can simply use them as positional parameters.

If your site uses ?n=Group.Page to specify the pagename then having a field (:input hidden name=n value={$FullName}:) will allow your form to post to the current page as an alternative to fully specifying the action=url.

The (:input end:) directive ends the current form.

Note that this feature doesn't ensure that the form output is correct HTML -- it assumes the author knows a little bit of what he or she is doing. Notably, (:input form:) and (:input end:) shouldn't appear inside tables, and all form fields and controls should be inside an (:input form:)...(:input end:) block.

Standard input controls

The standard input controls are:

    (:input text name value size=n:)
    (:input hidden name value:)
    (:input password name value:)
    (:input radio name value:)
    (:input checkbox name value:)
    (:input select name value label:)
    (:input default default-name default-value:) 
    (:input submit name value:)
    (:input textarea name [=value=] rows=n cols=n:)
    (:input reset name label:)
    (:input file name label:)
    (:input image name "src" alt:)

Where name and value are in the HTML syntax: name="addr" value="808 W Franklin".

For most controls the markup has the form:

    (:input type name value parameter=value:)

where type is the type of input element (described below), name is the name of the control, value is its initial value, and parameters are used to specify additional attributes to the control. If value contains spaces, enclose it in quotes; if it contains newlines (for textarea and hidden elements), enclose it in [=...=].

For example, the following creates a text input control with a size of 30 characters:

(:input text authorid "Jane Doe" size=30:)

For convenience, an author can also specify name and value arguments directly using name= and value= attributes (same as HTML):

(:input text name=authorid value="Jane Doe" size=30:)

For the textarea control a value can be set from PmWiki 2.2.0beta45 onwards. Enclose the value in [=...=] if it contains spaces or new lines.

The submit control will more often be written as:

    (:input submit value=label:)

Here's a more complete example, e.g., for a login prompt:

(:input form "http://www.example.com":)
(:input hidden action login:)
||     Name:||(:input text username:)    ||
|| Password:||(:input password password:)||
|| ||(:input submit value="Log In":) ||
(:input end:)

Name:
Password:
 

General form field attributes

  • (:input ... focus=1:) Setting focus=1 causes that field to receive the initial focus when the form is first opened.
  • The following advanced HTML attributes are supported: name, value, id, class, rows, cols, size, maxlength, action, method, accesskey, tabindex, multiple, checked, disabled, readonly, enctype, src, alt. For a more detailed description, see their counterparts in the w3c reference: HTML forms (not all of them can be used for all types of form fields).

(:input select ... :)

The basic form of a select box is a sequence of options:

(:input form:)
(:input select name=abc value=1 label=alpha :)
(:input select name=abc value=2 label=beta  :)
(:input select name=abc value=3 label=gamma :)
(:input submit:)
(:input end:)

The values can be specified positionally:

 (:input select abc 1 alpha :)

We can specify the size of the selection box:

 (:input select abc 1 alpha size=3 :)

You can specify a multiple select box:

 (:input select abc 1 alpha size=3 multiple:)

To have an element selected, use selected=selected:

 (:input select abc 2 beta selected=selected:)

Note that to have two select boxes inline, not only should you give them different name= parameters, but also place a separator, like a character, &nbsp; or even the null sequence [==] between them:

(:input form:)
(:input select name=FIRST value=1:)(:input select name=FIRST value=2:)[==]
(:input select name=SECOND value=3:)(:input select name=SECOND value=4:)
(:input end:)

See Also

Compatible recipes:

  • Cookbook:PmForm Form processing engine for PmWiki
  • Cookbook:Fox Form processor to add, replace, copy, delete content plus upload files and send email notifications using templates and Input markup
  • Cookbook:Wiki Forms Use a form template to create, edit and list wiki pages
  • Cookbook:ProcessForm Maintain values in fields and make PVs? of the form name/values when a form is submitted

SimultaneousEdits

PmWiki has support for handling the case where multiple authors attempt to edit the same page nearly simultaneously. Here's the basic scenario for systems where simultaneous edits are not handled:

  • Alice starts to edit a page.
  • Before Alice saves her edits, Bob requests an edit of the same page, and receives the page text prior to Alice's edits.
  • Bob finishes with his edits and hits "save".
  • Alice finishes editing her page, hits "save", and since she was working from a version of the page from before Bob had made his changes, she wipes out Bob's edits in the process.

PmWiki's simultaneous edit feature detects when this occurs, and instead of saving Alice's edits PmWiki presents Alice with a message that someone else changed the page while she was editing it. Furthermore, Bob's changes are merged into Alice's copy of the page, with any conflicts highlighted by <<<<<<< and >>>>>>>. Alice can then fix things as appropriate and save the updated page, or, if Alice is lazy, she can just hit "save" a second time and leave it to someone else to fix.

The simultaneous edits feature is also invoked whenever someone requests a page preview; thus if a page changes while previewing a page the author gets notification and can see the merged results.

How can I test/experiment with this feature?

  1. Open up two browser windows and select the same page to be edited in each window (e.g., try WikiSandbox?action=edit).
  2. In one browser window, make some changes to the page and then save those changes.
  3. In the second browser window, make some different changes to the same page and hit "save". Since the page changed after the edit form was loaded into the second window, there's a potential edit conflict and you'll receive the "edit conflict message".
  4. You can make any adjustments in the second window, and press "Save" again to save the changes.

Notice

Some server environments such as Windows and PHP running in safe_mode are unable to use the simultaneous edits capability distributed with PmWiki. See Cookbook:SimultaneousEdits for a solution for these environments.


WikiStructure

Authors have a range of options to choose from when organizing a collection of wiki pages. Used in combination, these give a lot of flexibility. An effective wiki will use all of these to optimize

  • content
  • navigation

These are the two most important aspects of a website.

Wiki Word
The most powerful organizing principle is the author's choice of page names. When a search returns a list of pages, their names need to be clear enough to guide a visitor to the right place.
Providing a network of links to other points in the wiki, with or without wiki words, is the primary means of navigating a wiki.
Wiki Page
A page with text (and images), where the text can contain for instance WikiWords that automatically becomes a link to another WikiPage.
Wiki Group
PmWiki requires every page to be a member of a group. A group is like a wiki within a wiki; it can have its own presentation look, security controls and navigation aids. With default configuration, WikiWords are only searched inside the current group, and you use either OtherGroup/MyWikiWord or OtherGroup.MyWikiWord to refer to pages in other groups (see Links).
Wiki Trails
A collection of pages, either in the same group or across multiple groups, can be designated as a trail. A visitor can move from stop to stop by clicking on next and previous links.
Categories
Individual wiki pages can also be grouped by having tags and links to a common "category" page; we say that any pages that link to a common page are in a "category" defined by that page. PmWiki uses the [[!category]] markup as a shorthand to place a page into a category with other pages containing the same markup.
The shortcoming of categories is that categories do not distinguish between the declaration of a category ([[!structure]]) and the link to a category ([[Category/Structure]]).
Page text variables
A newer and more powerful concept than Categories, pages can use one of more page text variables to store page attributes. These can the be used in page lists.
Page lists
Page lists provide a powerful means of presenting lists of relevant pages, or selection of data from within a page. Lists are template based and are highly customizable.
Include other pages
The capability to include parts of other pages also provides a flexible means of sharing content between pages.
Search
Being able to search is a fundamental requirement of a website. In PmWiki search, like pagelists is both powerful and highly customizable.

WikiGroup

PmWiki pages are organized into groups of related pages. This feature was added to PmWiki to allow authors to create their own wiki spaces of specialized content on their own, without having to become, or rely on, wiki administrators. See Pm's post to the pmwiki-users mailing list.

By default, page links are between pages of the same group; to create a link to a page in another group, add the name of the other group and a dot or slash to the page name. For example, links to Main/WikiSandbox could be written as:

* [[Main.WikiSandbox]]
* [[Main/WikiSandbox]]
* [[(Main.Wiki)Sandbox]]
* [[Main.WikiSandbox | link text]]
* [[Main.WikiSandbox | +]]

To link to the default home page of a group, the name of the page can be omitted, like this:

* [[Main.]]
* [[Main/]]

Creating groups

Creating a new group is as easy as creating new pages; simply edit an existing page to include a link to the new group's default home page (or any page in the new group) then click on the '?' to edit the page. As a rule, group names must start with a letter (but this can be changed by the wiki administrator by adding

$GroupPattern = '[[:upper:]\\d][\\w]*(?:-\\w+)*';

in config.php).

For example, to make a default page in the group Foo, create a link to [[Foo/]] (or [[Foo.]]). To make a page called Bar in the group Foo, create a link to [[Foo/Bar]] and follow the link to edit that page.

Groups in a standard PmWiki distribution

  • Main: The default group. On many wikis, it contains most of the author-contributed content. Main.HomePage and Main.WikiSandbox come pre-installed.
  • PmWiki: An edit-protected group that contains PmWiki documentation and help pages.
  • Site: Holds a variety of utility and configuration pages used by PmWiki, including
    SideBar, Search, Preferences, Templates, and AllRecentChanges.
  • SiteAdmin?: Holds a number of password protected administration and configuration pages used by PmWiki, including
    ApprovedUrls, and Blocklist
  • To list all the groups in a site, try searching for "fmt=group".
  • To list all the pages in a group, try searching for "GroupName/".

Special Pages in a Group

By default, the Recent Changes page of each group shows only the pages that have changed within that group; the Site.All Recent Changes page shows all pages that have changed in all groups.

Each group can also have Group Header or Group Footer pages that contain text to be automatically prepended or appended to every page in the group. A group can also have a Group Attributes page that defines attributes (read and edit passwords) shared by all pages within the group.

Each page can also have its own individual read/edit password that overrides the group passwords (see Passwords).

Finally, wiki administrators can set local customizations on a per-group basis--see Group Customizations.

Group's default page

The default "start page" for a group is a page whose name is:

  1. the same as the group (Foo/Foo)
  2. HomePage (HomePage?)
  3. a name that the administrator has assigned to the {$DefaultName} variable in the configuration.php file.

Note, on this site, the value of {$DefaultName} is HomePage and, thus, the default home page would be HomePage?.

You can usefully change the default search order for an entered page name by setting the variable $PagePathFmt in config.php, eg

$PagePathFmt = array('$Group.$1', '$1.$DefaultName', '$1.$1', '$DefaultGroup.$1', 'Profiles.$1');

where "$1" is the name of the page entered.

As noted above, when linking to the default home page, authors can omit the page name and simply identify the group followed by a forward slash ([[Foo/]]).

Note the forward slash is required to ensure that the link unambiguously points to the identified group. If the slash is omitted, the link can end up being interpreted as pointing to an existing (or new) page in the current group (if the group, or its default home page, do not exist).

Subgroups? Subpages?

No, PmWiki does not have subpages. Pm's reasons for not having subgroups are described at PmWiki:Hierarchical Groups, but it comes down to not having a good page linking syntax. If you create a link or pagename like [[A.B.C]] PmWiki doesn't think of "B.C" as being in group "A", it instead thinks of "C" as being in group "AB", which is a separate group from "A". Wiki administrators can look at Cookbook:Subgroup Markup and Cookbook:Include With Edit for recipes that may be of some help with developing subgroups or subpages.

Restricting the creation of new groups

You can set PmWiki's $GroupPattern variable to only accept the group names you want to define. For example, to limit pages to the "PmWiki", "Main", "Profiles", and "Example" groups, add the following to local/config.php:

$GroupPattern = '(?:Site|SiteAdmin?|PmWiki|Main|Profiles|Example)';

With this setting, only the listed groups will be considered valid WikiGroups. You can add more groups to the list by placing additional group names separated by pipes (|).

See other solutions to this at Cookbook:Limit Wiki Groups and Cookbook:New Group Warning.

How can I get rid of the 'Main' group in urls for pages pointing to Main?

See Cookbook:Get Rid Of Main.

How can I limit the creation of new groups?

See Cookbook:Limit Wiki Groups.

Why doesn't [[St. Giles and St. James]] work as a link? (It doesn't display anything.)

Because it contains periods, and destroys PmWiki's file structure, which saves pages as Group.PageName. Adding those periods disrupts this format. Links may only contain words. If you need a link precisely as shown, the page must be named eg StGilesAndStJames? then you can use the (:title:) directive to have the page's title appear with periods (:title St. Giles and St. James:). (Although in US grammar the period is often omitted and in UK grammar the period must be omitted for contractions like St).

How can I delete a wiki group?

Normally you can't, as this requires an admin with server-side access to delete the file that makes up the group's RecentChanges page. But there is an option method of making it possible to delete RecentChanges pages from within the wiki if the admin enables the code found on Cookbook:RecentChanges Deletion.

How can I delete a wiki group's Group.RecentChanges? page?

Normally you can't, as this requires an admin with server-side access to delete a file. But there is an optional method of making it possible to delete RecentChanges pages from within the wiki if the admin enables the code found on Cookbook:RecentChanges Deletion.


GroupHeaders and GroupFooters?

Every WikiGroup can have GroupHeader and GroupFooter pages that contain markup that should be included at the beginning or end of each page within the group. This feature is useful for:

  • adding a disclaimer or heading to all of the pages of a group
  • defining custom WikiStyles that may be used for all pages in a group
  • replacing the default headers and/or footers for pages in a group (e.g., using (:noheader:) and or (:nofooter:) -- see PageDirectives).

To create a group header, just create a new page called YourGroup.GroupHeader. Group headers allow authors to create groups with custom headers and footers without having to coordinate with a wiki administrator.

The default GroupHeader or GroupFooter can be suppressed on an individual page (such as a group's HomePage) by using the (:nogroupheader:) and (:nogroupfooter:) markups on that page.

If a generic GroupHeader is used in one wikigroup (say, the Site wikigroup), then the code can be easily duplicated in the GroupHeader of any other group by using (:include Site.GroupHeader:). See IncludeOtherPages.

If you want a header or footer to appear when you print a page (action print), simply create a page called YourGroup.GroupPrintHeader or YourGroup.GroupPrintFooter and fill it with your markup.

You can also set the variable $GroupPrintHeaderFmt and $GroupPrintFooterFmt in the same way as $GroupHeaderFmt and GroupFooterFmt in order to change the header used when action=print.

See also

How do I set the same header or footer for all pages/groups?

The header and footer for each page are controlled by the variables $GroupHeaderFmt and $GroupFooterFmt. If your site-wide header and footer pages are Site.SiteHeader? and Site.SiteFooter?, you can add this in config.php:

### If you use Site.SiteHeader and Group.GroupHeader
$GroupHeaderFmt = '(:include {$SiteGroup}.SiteHeader'
  . ' basepage={*$FullName}:)(:nl:)' . $GroupHeaderFmt;

### If you use Site.SiteHeader instead of Group.GroupHeader
$GroupHeaderFmt = '(:include {$SiteGroup}.SiteHeader'
  . ' basepage={*$FullName}:)(:nl:)';

### If you use Site.SiteFooter and Group.GroupFooter
$GroupFooterFmt .= '(:nl:)(:include {$SiteGroup}.SiteFooter'
  . ' basepage={*$FullName}:)';

### If you use Site.SiteFooter instead of Group.GroupFooter
$GroupFooterFmt = '(:nl:)(:include {$SiteGroup}.SiteFooter'
  . ' basepage={*$FullName}:)';

Note that single quotes must be used in the lines above.

See also the Cookbook:AllGroupHeader recipe.

Instead of using an additional page, you could set any wiki text in $GroupHeaderFmt, for example:

$GroupHeaderFmt .= "Global message here.";

WikiTrails

The WikiTrails feature allows wiki authors to create "trails" through sequences of pages in the wiki. You simply specify pages and their order on a "trail index", and then place the navigation markup on the pages that you will be navigating.

(Don't confuse the pagelist directive with WikiTrails - they are different animals as explained in the Q and A below.)

Creating a trail

Before you can use a trail through a group of pages, you have to create a "trail index" on a separate page, which we will call the "trail index page". On that trail index page, you simply create a numbered or bulleted list of links. (So every numbered or bulleted list of links implicitly creates a trail.) It is important that each page name (link) be the first item following each bullet; any text or formatting in front of the page name will exclude it from the trail.
If you want to format your trail (list), you can include a CSS.

An example trail index page might contain the list:

PmWiki philosophy
Design notes (The first link will, and the second link won't, be in the trail defined by (definition list))
  • Security (This won't be in the trail because its preceded by a (hidden) anchor)
  • Links (This won't be in the trail because its preceded by a (hidden) %newwin% style)
  • Troubleshooting (This won't be in the trail because its preceded by (hidden) italic style markup)

The list above creates the following "wikitrail", displayed using a pagelist:

(:pagelist trail={$FullName}#trailstart#trailend fmt={$FullName}#traillist:)

Observations

  1. In general, indentation levels in the page list don't matter -- trails are a linear sequence of pages.
  2. A page is part of the trail only if the page link immediately follows the list markup.
  3. The list itself can be delineated by the use of anchors, allowing for multiple lists on a page, or for some list items to be excluded.

Trail types

PmWiki defines 2 trail markups:

  • <<|[[Trail Index Page]]|>> displays as "<< PreviousPage | Trail Index Page | NextPage >>".
  • <|[[Trail Index Page]]|> displays as "< PreviousPage | Trail Index Page | NextPage >", except the appropriate arrow is omitted at the beginning and end of the trail.

Trail link syntax

The trail link has the same syntax as a standard link, this means for example you can specify

  • <|[[TrailIndexPage | +]]|>

Trail links can be restricted by anchors (links to a specific location within a page), this means you can have more than one trail on a page, or start a trail from a specific location in a page.

  • <|[[Trail Index Page#trailstart#trailend]]|>

Using the trail

What makes a trail "work" is adding trail markup on the pages in the trail (i.e. the pages that are listed in the bullet/numbered list on the trail index page).

To build a trail, add trail markup like <<|[[TrailIndexPage]]|>> to a page, where TrailIndexPage is the page, described above, containing the bulleted list of pages in the trail. PmWiki will display the trail markup with links to any previous and next pages in the trail.

The trail markup can be placed anywhere in a page, and a page can contain multiple trail markups. If you are adding a trail to every page in a group, consider setting the trail markup in the GroupHeader or GroupFooter pages instead of on every individual page in your group.

Path trail

^|[[TrailIndexPage]]|^ treats the list levels as a hierarchy and displays the "path" to reach the current page (i.e., a "breadcrumb" trail). In the example trail above, the markup ^|TrailIndexPage|^ on TrailPage4 would display as "TrailIndexPage | TrailPage2 | TrailPage4".

Wiki administrators can change the trail separator of the "path" trail ( ^|[[TrailIndexPage]]|^ ) from the default | by setting the variable $TrailPathSep in the config.php file. For instance $TrailPathSep = ' > '; will output "TrailIndexPage > TrailPage2 > TrailPage4".

Circular trails

Typically, a trail is a linear list with a first and a last page. However, the trail can be made "circular" by repeating the first page as the last item in the trail index:

 * [[TrailPage1]]
 * [[TrailPage2]]
 ...
 * [[TrailPageN]]
 * [[TrailPage1]]

If the trail index page is intended to be read by others, the last item can be made invisible inside an (:if false:) block:

 * [[TrailPage1]]
 * [[TrailPage2]]
 ...
 * [[TrailPageN]]
 (:if false:)
 * [[TrailPage1]]
 (:ifend:)

Cross Group Trails

Before version 2.2.1, if your trail contains pages in different groups, it should use full [[Group.Name]] links instead of just [[Name]].

Other notes

  • There is no space between and [[link]] and ; same for the other trail markups.
  • Note that non-existing pages will appear in the WikiTrail as links.

Trail style

PmWiki encapsulates the trail with a wikitrail css class. This allows the wiki trail to be customised by defining CSS for the wikitrail in the local.css file.

Trail in page lists

Trails from a single page can only be displayed using the pagelist trail parameter. For example

(:pagelist trail=PmWiki/WikiTrails fmt=PmWiki.WikiTrails#traillist order=random count=3:)

A simple example of a WikiTrail

1) On the TrailIndexPage?:

* [[MyTrailPage1]]
* [[MyTrailPage2]]
* [[MyTrailPage3]]

2) On the pages MyTrailPage1?, 2, and 3:

<<|[[TrailIndexPage]]|>>

Questions

What's the difference between a PageList and a WikiTrail?

The pagelist directive dynamically generates a list of pages. There are many ways to generate the list, including using a WikiTrail as the source. The pagelist directive then displays the pages that match the criteria using an optional template - for example displaying each page name on a separate line as a link or including the entire content. The pagelist directive currently does not have built-in navigation markup that you can put on the pages in the list. By contrast, WikiTrails are simply specified via links on an "index" page and you can put previous-next navigation markup on each page. The two serve very different purposes. WikiTrails are useful for specifying the pages in web feeds, for creating a "tour" through a predefined set of pages, and many other things.


PageHistory

When PmWiki is called with '?action=diff', it displays a summary of past edits on a page. Each past edit is shown in a box which shows lines added, changed or deleted during that edit in a before & after format.

Below each box is a "Restore" link. Clicking the link will open an edit box with the page as it was before that edit. You can make changes or simply click Save to restore the text.

There are two additional options specific to PageHistory:

  • Hide minor edits - hides any edit that the author marked as 'minor'. - This is done by adding "&minor=n" to "?action=diff". The default value for this is to show minor edits with "&minor=y"
  • Show changes to output - It shows changes to the rendered output (as opposed to the normal display which shows changes to the wiki-markup). This is done by adding "&source=n" to "?action=diff". You can show changes to markup (the default behavior from 2.2.13) with "&source=y".
  • You can set both by using "?action=diff&source=y&minor=y".

In the default mode "Show changes to markup", you can disable word-level highlighting of differences by adding to config.php such a line:

  $EnableDiffInline = 0;

A page's history is kept for the number of days given by the $DiffKeepDays and $DiffKeepNum variables (set by the site's wiki administrator). When a page is edited, any page history information older than both these values is automatically discarded.

Note that a specific page revision isn't removed from the page until the first edit after the time specified by $DiffKeepDays has elapsed. Thus, it's still possible for some pages to have revisions older than $DiffKeepDays -- such revisions will be removed the next time those pages are edited.

See also

Is there a way to remove page history from page files?

1. Administrators can clean page histories using the Cookbook:ExpireDiff recipe.

2. Administrators with FTP file access can download individual pages from the wiki.d directory, open them in a text editor, manually remove history, and re-upload the files to wiki.d/ directory. Care must be exercised, when manually editing a page file, to preserve the minimum required elements of the page and avoid corrupting its contents. See PageFileFormat#creating.

3. Edit the page. Select all the contents of the edit text area and cut them to the clipboard. Enter delete into the text area and click on the save and edit button. Select all the contents of the edit text area and paste the contents of the clipboard over them. Click on the save button. This will remove all of the page's history up to the final save in which the pasted material is re-added.

How can I restrict viewing the page history (?action=diff) to people with edit permission?

In the local/config.php file, set

$HandleAuth['diff'] = 'edit';

In case of this restriction is set up on a farm, and you want to allow it on a particular wiki, set in your local/config.php :

$HandleAuth['diff'] = 'read';

Passwords

PmWiki has built-in support for password-protecting various areas of the wiki site. Authors generally want to be able to apply passwords to individual pages or to wiki groups. Wiki Administrators can apply passwords to individual pages, to wiki groups, or to the entire site. Setting an edit password on a page or group (or the entire site) is one of the most common ways to stop spam. As with any access control system, the password protection mechanisms described here are only a small part of overall system and wiki security.

As an author editing pages...

An author will generally set 3 types of passwords:

  1. to control who can see a page or group, use read passwords
  2. to control who can edit a page or group, use edit passwords
  3. to control who can alter the passwords used to protect a page or group, use attr passwords

If required most page actions can be password protected.

Protect an individual page

To set a password on an individual wiki page, add the page action

?action=attr

to the page's URL (address) to access its attributes. Using the form on the attributes page, you can set or clear the read, edit, or attr passwords on the page. In the form you enter the passwords as cleartext; PmWiki encrypts them for you automatically when it stores them.

Additional options:

  • Leaving a field blank will leave the attribute unchanged.
  • To remove a password from a page (reverting back to the group's or site's default), enter
clear
  • To indicate that the page can be edited even if a group or site password is set, enter
@nopass
  • To lock a page for everybody but the admin, enter
@lock
  • To assign the site's site-wide passwords to the read, edit, or attr password for the page, enter
@_site_edit, @_site_read or @_site_upload

Protect a wiki group of pages

To set a password on a wiki group is slightly more difficult -- you just set the passwords on a special page in each group called

First, you can get to the attributes page for GroupAttributes by entering a URL (address) like

http://example.com/pmwiki/pmwiki.php?n=GroupName.GroupAttributes?action=attr

Replace example.com with your domain name, and GroupName? with the name of the group

Then, using the form on the attributes page, you can set or clear the read, edit, or attr passwords for the entire group. In the form you enter the passwords as cleartext; PmWiki encrypts them for you automatically.

Additional options:

  • To remove a password from a group (reverting back to the site's default), enter
clear
  • To indicate that the group can be edited even if a site password is set, enter
@nopass
  • To lock a group for everybody but the admin, enter
@lock
  • (Beginning with Ver 2.2.3) To assign the site's site-wide passwords to the read, edit, or attr password for the group, enter
@_site_edit, @_site_read or @_site_upload

Passwords

Passwords may consist of any combination of characters, except double "quotes" or 'apostrophes'. Passwords with spaces or colons must be entered using quotes, eg "foo bar" or "foo:bar". Obviously longer is better, and on some systems passwords need to have 4 or more characters.

Multiple passwords

Multiple passwords for a page, group or site are allowed. Simply enter multiple passwords separated by a space. This allows you to have a read password, a write password, and have the write password allow read/write access. In other words, if the read password is

alpha

and the edit password is

beta

then enter

Set new read password: alpha beta
Set new edit password: beta

This says that either

alpha

or

beta

can be used to read pages, but only

beta

may edit. Since PmWiki checks the passwords you've entered since the browser has been opened, entering a read password that is also a write password allows both reading and writing.

Protect the site

Passwords can be applied to the entire wiki website in config.php. See passwords administration for details.

administrator

As an administrator ...

You can set passwords on pages and groups exactly as described above for authors. You can also:

  1. set site-wide passwords for pages and groups that do not have passwords
  2. use attr passwords to control who is able to set passwords on pages
  3. use upload passwords to control access to the file upload capabilities (if uploads are enabled)
  4. use an admin password to override the passwords set for any individual page or group
  5. use SiteAdmin.AuthList to view the permissions settings for pages that have permissions set.

For more information on password options available to administrators, see PasswordsAdmin.

Which password wins?

In PmWiki, page passwords override group passwords, group passwords override the default passwords, and the admin password overrides all passwords. This gives a great deal of flexibility in controlling access to wiki pages in PmWiki.

The special page SiteAdmin.AuthList is a page list of all pages with access permissions set.

Opening access to pages in protected groups/sites

Sometimes we want to "unprotect" pages in a group or site that is otherwise protected. In these cases, the special password

@nopass

is used to indicate that access should be allowed to a page without requiring a password.

For example, suppose Main.GroupAttributes has an edit password set, thus restricting the editing of all pages in Main. Now we want Main.WikiSandbox to be editable without a password. Using

clear

for the edit password for Main.WikiSandbox doesn't unprotect the page, because the password is being set by the group. Instead, we set the edit password for Main.WikiSandbox to the special value

@nopass

which tells PmWiki to ignore any site-wide or group-level passwords for that page.

How can I password protect all the pages and groups on my site? Do I really have to set passwords page by page, or group by group?

Administrators can set passwords for the entire site by editing the config.php file; they don't have to set passwords for each page or group. For example, to set the entire site to be editable only by those who know an "edit" password, an administrator can add a line like the following to local/config.php:

    $DefaultPasswords['edit'] = crypt('edit_password');

For more information about the password options that are available only to administrators, see PasswordsAdmin.

I get http error 500 "Internal Server Error" when I try to log in. What's wrong?

This can happen if the encrypted passwords are not created on the web server that hosts the PmWiki.
The crypt function changed during the PHP development, e.g. a password encrypted with PHP 5.2 can not be decrypted in PHP 5.1, but PHP 5.2 can decrypt passwords created by PHP 5.1.
This situation normally happens if you prepare everything on your local machine with the latest PHP version and you upload the passwords to a webserver which is running an older version.
The same error occurs when you add encrypted passwords to local/config.php.

Solution: Create the passwords on the system with the oldest PHP version and use them on all other systems.

How can I create private groups for users, so that each user can edit pages in their group, but no one else (other than the admin) can?

Modify the edit attribute for each group to id:username, e.g. set the edit attribute in JaneDoe.GroupAttributes? to id:JaneDoe?.

There is a more automatic solution, but it's probably not a good idea for most wikis. Administrators can use the AuthUser recipe and add the following few lines to their local/config.php file to set this up:

    $group = FmtPageName('$Group', $pagename); 
$DefaultPasswords['edit'] = 'id:'.$group;
include_once("$FarmD/scripts/authuser.php");

This automatically gives edit rights to a group to every user who has the same user name as the group name. Unfortunately it also gives edit rights to such a user who is visiting a same-named group not just for pages in that group, but for any page on the wiki that relies on the site's default edit password. This can create security holes.

How come when I switch to another wiki within a farm, I keep my same authorization?

PmWiki uses PHP sessions to keep track of authentication/authorization information, and by default PHP sets things up such that all interactions with the same server are considered part of the same session.

An easy way to fix this is to make sure each wiki is using a different cookie name for its session identifier. Near the top of one of the wiki's local/config.php files, before calling authuser or any other recipes, add a line like:

    session_name('XYZSESSID');

You can pick any alphanumeric name for XYZSESSID; for example, for the cs559-1 wiki you might choose

    session_name('CS559SESSID?');

This will keep the two wikis' sessions independent of each other.

Is it possible to test the password level for display and/or if condition? Example: * (:if WriterPassword:) (display Edit link) (:ifend:)

You can use (:if auth edit:). See ConditionalMarkup.


Categories

Purpose of categories

Categories (also known as "tags") are a way to organize and find related pages. Categories are implemented by default in PmWiki 2, and in most wikis they don't require any special code or markup, they're just a useful convention. The idea is that every page that falls into a particular subject area should have a link to a shared page containing links to other pages on that subject. These pages are created in the Category group, and thus these subject areas are called "categories".

Using categories

Getting categories to work requires a single step: adding links to each category. A category named Subject is created by adding a link to Category.Subject on any page. When you add the link to a page, the page can be described as being in the category "Subject".

There is a special markup for creating these links which makes categories work more smoothly: [[!Subject]] will create a link to Category.Subject. So [[!Subject]] is a kind of shortcut to the page Subject in the category group.

A Category.GroupFooter file is included in the PmWiki release that contains the line (:pagelist link={*$FullName} list=normal:) so that whenever a category page is displayed, it will show a list of links to pages that reference that page in the category group. Like any other page in wikilib.d you can modify this page and it will not get overwritten by another release.

It is worth noting that rather than using Category.GroupFooter, the pagelist directive can be added to Category.GroupHeader to similar effect; it just depends on whether you'd prefer to have the list of pages appear before or after any text that you add to the individual category pages (which can be edited just like normal pages).

Because we use the normal PageList link= markup, you can use it not only in the category group. If you want to show all pages belonging to the category Subject you can use on any wiki page (:pagelist link=Category.Subject list=normal:).

Similarly, there's no requirement that a "category page" has to be in the Category group -- any page can define a "category" of pages that link to it.

An administrator can override the default category group name of "Category" by setting the $CategoryGroup variable in config.php to another group name. (Normally a change such as this should be done during initial setup on a new wiki; changing this on a wiki with existing content can cause problems with pagelists unless each page with a category is re-saved.)

A page author can also link to a category list without adding the linking page to the category by using [[ {Category.Subject$PageUrl} | Subject ]]. This will create a link that looks like [[!Subject]] without adding the linking page to the category listing.

Recap

So, by adding the link [[!Subject]] to a page, a link to that page will automatically appear on the page Category.Subject, as long as Category.GroupFooter has been tweaked appropriately. Thus, you can create a page that automatically creates an alphabetized list of all movies discussed on your wiki by creating links to [[!Movies]] on each film's page; the resulting automatic list would be on the page Category.Movies .

authors (advanced)

Category nesting

Categories have the potential for even greater usefulness because Category.* pages can themselves be placed into categories! To follow an excellent example from John Rankin, let's suppose we have the following film pages in the categories listed to the right:

Film.ShaunOfTheDead   [[!Horror]] [[!Comedy]] [[!2003]]
Film.InMyFathersDen   [[!Drama]] [[!2004]]
Film.TheCorporation   [[!Documentary]] [[!2003]]

Now then, we can create Category.Horror, Category.Comedy, Category.Drama, and Category.Documentary, and in each one of those pages we put [[!Genre]]. In Category.2003 and Category.2004, we put [[!Year]].

So, what happens when we display Category.Genre ? We see links to "Comedy", "Drama", "Documentary", and "Horror", because they're in the Genre category. When we click on one of those links, we see all of the films listed in one of those categories. Similarly, if we click on Category.Year, we see links to "2003" and "2004", each of which in turn displays the list of films for that year.

Finally, in Category.Genre and Category.Year we can put [[!Category]], which makes them "top-level" categories reachable from the Category.Category page. Voila, we now have an instant "hierarchy":

Category.Category
    Category.Genre
        Category.Comedy
            Film.ShaunOfTheDead
        Category.Drama
            Film.InMyFathersDen
        Category.Documentary
            Film.TheCorporation
        Category.Horror
            Film.ShaunOfTheDead
    Category.Year
        Category.2003
            Film.ShaunOfTheDead
            Film.TheCorporation
        Category.2004
            Film.InMyFathersDen

Note however that this isn't a "strict" hierarchy--i.e., any page or category can appear simultaneously in multiple categories. For example, Category.Documentary could be a member of both the Genre and top-level category listings.

Each category page can have content text before the generated list, e.g., to give a generic description of things in the category. (Or it can be empty, which works fine.) It can also contain associations to related categories ("see also" references). For example, in a tourism wiki, the ''bed and breakfast" category might contain a see-also reference to the "self-catering" category.

administrators (intermediate)

The guts of the category markup

As mentioned, all of the necessary markup features for Categories are enabled by default in current releases of PmWiki 2.0, but here's how they work for those who are interested. The use of the Category group as the repository for all categories is determined by setting the $CategoryGroup variable, and the special [[!Subject]] markup is activated by a call to the Markup() function:

SDV($CategoryGroup,'Category');
Markup('[[!','<links','/\[\[!([^\|\]] ?)\]\]/',
  "<span class='category'>[[$CategoryGroup/$1]]</span>");

Coming up with good category schemes

The hard part about using categories is choosing a good vocabulary. Site content managers may wish to follow the Guidelines for the establishment and development of monolingual thesauri (ISO 2788-1986) and the Guidelines for the establishment and development of multilingual thesauri (ISO 5964-1985). Questions to think about include:

  • whether a scheme already exists and can be reused
  • number of levels in a multilevel scheme (not too shallow, not too deep -- e.g. 3)
  • number of categories per page (not too many, not too few -- e.g. 3)
  • consistent use of singular ([[Mercury]] is a [[!planet]]) or plural ([[Mercury]] is in the [[!planets]] category)
  • disambiguation and use of phrases ([[!musical instruments]] and [[!medical instruments]]) or Cookbook:Subpage Markup ([[!Instruments*Musical]] and [[!Instruments*Medical]])

Or you can just let people use whatever category terms they find meaningful. A vocabulary (or "folksonomy") will emerge over time.

Showing a list of categories

To show a list of categories we can use a pagelist for the pages in the category group. For instance the following will list pages in the Category group, put it on page Category.Category for convenience, or on any other page:

(:pagelist group=Category list=normal fmt=#title:)

But there is a problem: Just adding a category markup to a page will not create a corresponding category page, even though following the link will show the page with a list of pages linking to it!
To have category pages automatically created in group 'Category' add the following to config.php:

$AutoCreate['/^Category\./'] = array('ctime' => $Now, 'text' => $page['text']);

Change 'Category' to the name of your category group. You can also add more definitions for more category groups, useful if you use a recipe like Cookbook:Tagger which allows multiple category groups.

See also EditVariables#AutoCreate


PageLists

PmWiki comes with two directives for generating lists of pages -- (:pagelist:) and (:searchresults:). Both directives are basically the same and each accepts the parameters documented below. The primary difference between the two is that searchresults generates the "Results of search for ..." and "### pages found out of ### searched" messages around the results.

The (:searchbox:) directive generates a search form (input text box) to submit search queries. The markup generally accepts the same parameters as (:pagelist:), which makes it possible to restrict, order and format searchresults in the same ways that are described below for a (:pagelist:). For more information about the (:searchbox:) directive, and the ways in which it differs from a (:pagelist:), skip to the section below.

Basic syntax

  • (:pagelist:)
without any arguments shows a bulleted list of all pages, as links, ordered alphabetically and in groups.
shows a pagelist according to the parameters supplied. Parameters are optional.

Parameters

Any argument supplied within (:pagelist:) that isn't in the form 'key=value' is treated as text that either must (or must not) exist in the page text.

The minus sign (-) can be used to indicate things that should be excluded. Thus

(:pagelist trail=PmWiki.DocumentationIndex list=normal apple -pie:)

lists all "normal" pages listed in the Documentation Index trail that contain the word "apple" but not "pie".

With page text variables

You can also use page text variables as a key to list pages according to the existence of a page text variable. Eg :

(:pagelist $:pagetextvar=avalue:)

lists pages having $:pagetextvar set to avalue.
Minus sign (-), wildcards (?*) and a comma separated list of values also works when specifying a selection based on pagetextvariables. Eg :

(:pagelist $:apagetextvar=t*,-test:)

lists pages having $:apagetextvar like 't*' but not 'test'.
Examples:

PTV is set (is not empty):(:pagelist $:MyPageTextVariable=- :)
PTV is empty or not set:
 (ie, is not set to one char followed by 0 or more chars)
(:pagelist $:MyPageTextVariable=-?* :)
PTV is not VALUE:(:pagelist $:MyPageTextVariable=-VALUE :)
PTV is set and not YES:(:pagelist $:MyPageTextVariable=?*,-YES :)

Be aware that if using (:pagelist $:MyPTV=$:YourPTV :) PTVs? include PmWiki formatting, so you may not get the matches you expect. Currently the only way around this is to use wild cards, so if the formatting is embedded you may be out of luck.

With page variables (PV)

Page variables can be used within pagelists in the same way as page text variables. See Page Text Variables above for more details. Simply use $var instead of $:var.

group= and name=

The "group=" and "name=" parameters limit results to pages in a specific group or with a specific name:

All pages in the Pmwiki group: (:pagelist group=PmWiki :)
All pages except those in the PmWiki or Site groups: (:pagelist group=-PmWiki,-Site :)
All RecentChanges pages (:pagelist name=RecentChanges :)
All pages except RecentChanges (:pagelist name=-RecentChanges :)

Wildcards

Name and group parameters can contain wildcard characters that display only pages matching a given pattern:

  • An asterisk (*) represents zero or more characters
  • A question mark (?) represents exactly one character

Examples:

All pages in any group beginning with "PmWiki" (:pagelist group=PmWiki* :)
All pages in any group beginning with "PmWiki", except for Chinese (:pagelist group=PmWiki*,-PmWikiZh :)
All pages in the PmCal group with names starting with "2005": (:pagelist name=PmCal.2005* :)
All Cookbooks with names beginning with a A and a B letter
note the different separators used for the same result
(:pagelist group=Cookbook name=A*,B*   :)
(:pagelist group=Cookbook name="A* B*" :)
(:pagelist group=Cookbook name=[AB]*   :)
(:pagelist group=Cookbook, name=[AB]*   :)

If you want to use multiples conditions in name you need to use quotes or commas to delimit the string.

trail=

The "trail=" option obtains the list of pages to be displayed from a WikiTrail:

  • Display pages in the documentation by modification time
(:pagelist trail=PmWiki.DocumentationIndex order=-time:)
  • Display five most recently changed pages
(:pagelist trail=RecentChanges count=5:)

list=

The "list=" option allows a search to include or exclude pages according to predefined patterns set by the administrator.

fmt=

The "fmt=" option determines how the resulting list should be displayed. PmWiki predefines several formats:

  • fmt=#bygroup - Display pages within groups (default format)
  • fmt=#simple - Display a simple ordered list of pages in the form Group.Name
  • fmt=#title - Display a list of pages by page title. Use "order=title" to have them sorted by title (default is to order by page name).
  • fmt=#group - Display a list of wikigroups (without listing the pages in the groups)
  • fmt=#include - Display the contents of each page in the list (note, this could take a very long time for long lists!)

These formats are defined by page list templates, which can be customized.

This format is not predefined by a page list template:

  • fmt=count - Display the number of pages in the list (note the absence of the "#"). In a trail, fmt=count counts existing and non-existing pages ; to limit count to existing pages, use : if="exists {=$FullName}" fmt=count (mailing list).

link=

The "link=" option implements "backlinks" -- i.e., it returns a list of pages with a link to the target. It's especially useful for category pages and finding related pages.

(:pagelist link=PmWiki.DocumentationIndex:)
  • all pages with links to the current page
(:pagelist link={$FullName}:)
  • all pages in the "Skins" category
(:pagelist link=Category.Skins:)

count=

The "count=" option provides the ability to

  • limit the pagelist to a specific number of pages
  • subsets of a list
  • return items from the end of a list, subsets of a list
  • display pages in reverse sequence
A simple bullet list of ten most recently modified pages

(:pagelist trail=Site.AllRecentChanges count=10 fmt=#simple:)

Display the first ten pages of a list

count=10 # display the first ten pages of list

Negative numbers specify pages to be displayed from the end of the list:

count=-10 # display last ten pages of list

Ranges may be specified using '..', thus:
count=1..10       # first ten pages of list
count=5..10       # 5th through 10th pages of list
Negative numbers in ranges count from the end of the list:

count=-10..-5 # 10th from end, 9th from end, ..., 5th from end

Omitting the start or end of the range uses the start or end of the list:
count=10..        # skip first ten pages
count=..10        # 1st through 10th page of list
count=-10..       # last ten pages of list
count=..-10       # all but the last nine pages
Ranges can be reversed, indicating that the order of pages in the output should likewise be reversed:
count=5..10       # 5th through 10th pages of list
count=10..5       # same as 5..10 but in reverse sequence
count=-1..1       # all pages in reverse sequence
"Reverse sequence" here refers to the sequence after any sorting has taken place. Therefore the three directives to the right are equivalent:
(:pagelist order=-name count=10:)
(:pagelist order=-name count=1..10:)
(:pagelist order=name count=-1..-10:) 

wrap=

The "wrap" option has the values, none and inline.

With "wrap=inline" and "wrap=none", the output from pagelist (markup or HTML) is directly embedded in a page's markup without any surrounding <div> class=...</div> tags.

With "wrap=inline", any surrounding <ul> is continued. Without "wrap=inline", the HTML output starts a new <ul>. This is important if you want to get a second level <ul> produced by the page list since starting a new <ul> with "**" doesn't yield a second level <ul> but <dl><dd><ul>...

"wrap=inline" likely has other effects since it suppresses the call to $FPLTemplateMarkupFunction (being MarkupToHTML? by default).

class=

By default, a pagelist has the 'fpltemplate' class. The 'bygroup', 'simple', 'group' and 'title' page list formats have specific class names fplbygroup, fplsimple etc. You can set any class using the class= parameter or by setting the $FPLFormatOpt array.

request=1

With (:pagelist [other parameters] request=1:) you can override most pagelist parameters, by providing request parameters in the URL. For example, (:pagelist order=name request=1:) will normally sort the list by name. But if the page's URL contains ?order=time, the list will be sorted by time. If the URL contains ?order=, the list will be unordered.

req=1

The req=1 parameter makes the pagelist execute only when the search terms are posted (that is, when the user presses "search" on a search form). Note that (:pagelist request=1 req=1:) works mostly like (:searchresults:) without the lines "Results of search for ..." and "X pages found out of Y pages searched". Both "request=1" and "req=1" are needed.

passwd=

The "passwd" option returns only those pages that have some sort of password attribute on them.

if=

The "if" option allows a condition to be specified as part of the pagelist processing, rather than from within the page list template. Only those pages for which the condition is true are retrieved. Anything that could go within an (:if ...:) can be used as a condition. For example

  (:pagelist if="date {(ftime %GW%V {*$Name})} {=$Name}" :)

returns all of the pages where the name is in the same week as that of the current page.

If any arguments within the quotes could contain a space they must be quoted:

  (:pagelist if="date 2009-01-01..2009-12-31 '{=$:Mydate}'" :)

order=

The "order=" option allows the pages in the list to be sorted according to different criteria. Use a minus sign to indicate a reverse sort. Multiple sorting criteria can be specified using a comma, and you can create your own custom pagelist sort order:

  • order=name - alphabetically by name (default order)
  • order=title - alphabetically by title rather than names
  • order=time - most recently changed pages last
  • order=ctime - time of page creation (see note)
  • order=group,title - by multiple criteria, in this instance sort by title within groups
  • order=random - shuffle the pages into random sequence
  • order=$:pagetextvarname - alphabetically by page text variable value
  • order=$pagevarname - alphabetically by page variable value

Also, the order= option allows custom ordering functions to be written.

  • Note: trail= preserves the order of the pages as they appear on the trail (unless you've specified order= explicitly or there is a default order in the page list template). So PmWiki's alphabetical default order does not apply when trail= is specified.
  • Note: ctime was added to pages only from pmwiki 2.1.beta15 onwards, pages created by earlier versions don't carry a ctime attribute and can't be sorted that way.

cache=0

Pagelist has the capability to cache lists which greatly speeds up processing (when $PageListCacheDir is set). Every once in a while this caching can result in undesired results. Specifying cache=0 disables caching.

Specifying variables as parameters

You can also specify variable values inline with the pagelist statement, and refer to the variables in the template using the {$$variable1} format:

(:pagelist fmt=#pagelist variable1="value" variable2="value2":)

This assumes that a site has $EnableRelativePageVars enabled, which is recommended in PmWiki 2.2.0 -- but disabled by default to help people upgrading from 2.1.x.

For example, in the template:

>>comment<<
[[#tvars]]
(:template default count=1 ParamName=Simon:)
Hi, {$$ParamName}, how are you today?
[[#tvarsend]]
>><<

(:template default count=1 ParamName?=Simon:) Hi, {$$ParamName}, how are you today?

This gives:

(:pagelist fmt=#tvars ParamName="Sam":)

(:pagelist fmt=#tvars ParamName="Sally":)

(:pagelist fmt=#tvars:)

Hi, Sam, how are you today?

Hi, Sally, how are you today?

Hi, Simon, how are you today?

See also $EnableUndefinedTemplateVars.

Examples

Include the contents of a random page from the Banners group:

(:pagelist group=Banners order=random count=1 fmt=#include list=normal:)

Display a simple list of the last ten recently changed pages:

(:pagelist trail=Site.AllRecentChanges count=10 fmt=#simple:)

Display the "top twenty" biggest cookbook pages:

(:pagelist group=Cookbook order=-size count=20 :)

The Searchbox Directive

The (:searchbox:) directive generally accepts the same parameters as (:pagelist:) and (:input text:) directives:

  • Pagelist parameters can be added to the input text of a searchbox (or to the markup, or both)
  • Input text box parameters can be added to the searchbox markup
    • An initial search string can be specified in the searchbox markup, but it must be in the form value='search string'. That search string is displayed in the input text and can be modified by when the search is run.
    • The size of the text input field can be specified with the size parameter, where "size=40" would specify the current default value.
      • Tip: If more than one searchbox appears on a page, adding a blank initial value like this value='', to the markup for each searchbox will prevent a search string for one box from populating all of the other boxes.
  • The target page for displaying searchbox results can be set with the parameter target=GroupName.PageName?. The default is the current page.
  • The entire searchbox form can be overridden by defining the $SearchBoxFmt variable in one's configuration file. If $SearchBoxFmt is defined, then the parameters to (:searchbox:) are ignored, and the content of the $SearchBoxFmt variable are used instead.

The additional parameter label="Label" can be used to change the label of the associated submit button:

 (:searchbox label="Search this wiki":)

The Searchresults directive

The (:searchresults:) directive generally accepts the same parameters as (:pagelist:) and (:input text:) directives.

Customizing "Results of search for..." and "3 pages found out of..."

To change the text surrounding the search results, customize the following and add it to local/config.php or $FarmD/local/farmconfig.php. Note that 'en' should be changed to the localized language.

XLSDV('en', array(
        'SearchFor' => 'Results of search for <em>$Needle</em>:',
        'SearchFound' => 
                '$MatchCount pages found out of $MatchSearched pages searched.'
));

Alternatively, adjust the 'SearchFor?' and 'SearchFound?' phrases in your translation pages.

The $SearchResultsFmt variable can also be set in local/config.php or $FarmD/local/farmconfig.php.

SDV($SearchResultsFmt, "<div class='wikisearch'>\$[SearchFor]
  <div class='vspace'></div>\$MatchList
  <div class='vspace'></div>\$[SearchFound]</div>");

See Also


DeletingPages

To delete a page, edit the page, select (highlight) all text in the edit textarea and replace it with the single word

delete

Note that it may be a good idea to add a comment to the field summary explaining why you deleted the page. (The field summary is usually found just below the edit textarea).

After saving the changes the page is deleted. As an added safety feature, the deleted page still exists on the server (with a timestamp) and can be restored to the former page by the wiki administrator.

If you suspect that a page has been deleted but aren't sure, have a look at the wikigroup's RecentChanges. Erasing a page counts as editing the page, and the activity is recorded there and on Site.AllRecentChanges.

The default word used for page deletion ("delete") can be changed in config.php by setting the variable $DeleteKeyPattern (see Edit Variables). If there is a danger of malicious page deletion it may be a good idea to change the delete word to something more obscure. There is also a recipe for creating a separate delete action at Cookbook:DeleteAction.

Removing deleted pages

The deleted pages are kept in the wiki.d directory, with an extension of ,del-123456789 where 123456789 is a unique number (timestamp). A wiki administrator may log into the server via FTP or SSH and periodically remove these files.

One way to remove the files is to delete them from your file manager. If you have shell access, you could use different commands, for example, go into the wiki.d directory and type one of these lines:

  rm -f *,del-*
  find . -name '*,del-*' -delete

Alternatively, the Cookbook:CleanUp recipe can purge those unused files. See also BackupAndRestore.

Deleting Wiki Groups & Categories: Once I create a Group or Category, how can I get rid of that group or category?

An admin can just remove the unwanted pages from wiki.d/ . Normally, doing it via the wiki doesn't resolve the problem, since it counts as an "update" which causes the Recent Changes page to be re-created, but it is possible to modify the site's configuration to allow deletion of the group's RecentChanges page -- see Cookbook:RecentChangesDeletion. To delete a category, first delete the [[!Category]] links from all pages to that category, then just delete the category page as explained above.


Installation

This page explains how to download and install PmWiki 2.1 and 2.2. Here's a list of related pages:

  • Requirements - Pre-requisites for running the PmWiki wiki engine
  • Upgrades - How to upgrade an existing PmWiki installation
  • Wiki Farms - Running multiple wikis from a single installation
  • Change Log - Log of changes made to PmWiki by Release

Improvements to these instructions are always appreciated. Just report any problems you encounter to the pmwiki-users mailing list or use the PmWiki Issue Tracking System.

Installing PmWiki

If you upgrade, please read the page Upgrades and Release notes.

1. Download

Download the latest stable version of PmWiki as a

Download the latest beta version from the PmWiki:Subversion page.

2. Unpack

Unpack the archive (tar zxvf pmwiki-latest.tgz or unzip pmwiki-latest.zip). This will create a pmwiki-x.y.z directory containing the PmWiki software. For example, the current "latest" should unpack to a directory named pmwiki-2.3.38. The files in this directory include:

  README.txt        An introductory document
  pmwiki.php        The main PmWiki script
  local/            Configuration scripts (local configuration files)
  cookbook/         Recipes (add-ons) from the Cookbook
  docs/             Brief documentation, sample configuration scripts
  pub/              Publicly accessible files
  pub/css/          Extra CSS stylesheet files [6]
  pub/guiedit/
  pub/skins/        Layout templates for custom look and feel
  scripts/          Scripts that are part of PmWiki
  wikilib.d/        Bundled default PmWiki pages

The pmwiki-x.y.z directory needs to be placed into a location accessible by your webserver (e.g., in a public_html directory of some sort). You can place files and directories using a number of methods -- FTP, or a Unix mv or cp command generally does the job.

Note: It is recommended to change the "pmwiki-x.y.z" directory name to be simply "pmwiki" or just "wiki".

3. Create directories

In most cases PmWiki will do this for you. Open a web browser to the pmwiki.php script on the server (i.e., not the one on your local computer or accessed using a file://... URL). PmWiki will then analyze your system configuration and provide instructions (if needed) for creating the wiki.d/ directory which will be used to hold the pages created for your site.

Otherwise, there are two ways to achieve this. (Use Filezilla or WinSCP to change FTP file/folder permissions.)

3a. You can create the wiki.d/ directory manually, and then give it full write permissions (i.e., "chmod 777 wiki.d"). Use this method when "safe mode" is activated in the server's PHP installation.
3b. On some systems you can let PmWiki create wiki.d/ by temporarily changing the permissions on the directory containing the pmwiki.php file to 2777. In Unix this is commonly done by changing to the directory containing pmwiki.php and executing the command
chmod 2777 .
(note the dot at the end). The chmod command also works in many FTP programs. Creating wiki.d/ in this manner will (1) make the directory writable so the web server can create the data directory it needs for the wiki files, (2) preserve group ownership of the directory so the installer account can manipulate the files created in this directory, and (3) make it more difficult for other accounts on the same server to access the files in wiki.d/.

After establishing directory permissions, try opening a browser to the pmwiki.php script again. If all is well, the wiki.d directory will have been created and you'll see the default home page.

Important: If you used method 3b, you should reset permissions by executing "chmod 755 ." in the directory containing pmwiki.php.

4. Initialize

Check out Initial Setup Tasks for other tasks you may want to perform to begin customizing your PmWiki installation. You might also want to peruse the Release Notes for further information.

5. Set language

If you want to use PmWiki in a different language download the international language pack as zip archive (i18n-all.zip) from http://pmwiki.org/pub/pmwiki/i18n/. Then extract it and copy the files into the wikilib.d/ directory as described above. Besides the -all file you can also download your country localization file only.

Languages available are:

There are two directories in the decompressed i18n archive, scripts and wikilib.d. Copy the files respectively contained in these directories to the scripts and wikilib.d of your PmWiki directory. For example, for French localization, PmWikiFr.* and PmWiki.* must be contained in the same directory.

Then, enable localization by adding an instruction to local/config.php to load the language translation page of your choice. For instance, XLPage('fr','PmWikiFr.XLPage'); loads the French language page PmWikiFr.XLPage.

Read more about this on Internationalizations.

Notes

  • The PmWiki distribution deliberately doesn't include an index.php file. You can easily add your own "wrapper script" in the same directory as pmwiki.php. Create a new file called index.php with the following single line of text (missing a closing " ?>" tag deliberately):
    <?php include_once('pmwiki.php');

Resist the temptation to rename pmwiki.php to index.php because if you rename the file it will not be overwritten during an upgrade.

  • If using the Unix tar command to unpack the archive in step 2 above, be sure that the files are created with sufficient permissions for the webserver to be able to access them. Usually you can ensure this by typing umask 002 on the command line before unpacking the tar file.
  • When installing on Windows you should take a look at Cookbook:SimultaneousEdits to enable simultaneous edits on that platform.
  • Additional tips can be found at Troubleshooting.

See also:

Should I rename pmwiki.php to index.php?

Renaming pmwiki.php is not recommended. Instead, create an index.php file that contains this single line

<?php include_once('pmwiki.php');

How do I make pmwiki.php the default page for a website?

Create an index.php file that runs PmWiki from a subdirectory (pmwiki/ for example) and place it in the site's web document root (the main directory for the website).

<?php chdir('pmwiki'); include_once('pmwiki.php');

Note: You will also need to explicitly set the $PubDirUrl variable (e.g. to "http://example.com/pmwiki/pub") in local/config.php .

How do I enable "Clean URLs?" that are shorter and look like paths to my wiki pages? Why does pmwiki.org appear to have a directory structure rather than "?n=pagename" in URLs??

See Cookbook:CleanUrls.

How can I run PmWiki on a standalone (offline, portable) machine ?

See Cookbook:Standalone or Cookbook:WikiOnAStick.


InitialSetupTasks

Once you have PmWiki running on your site (see Installation), you can customize it for your particular needs.

Most PmWiki configuration is performed in files called local/config.php and pub/css/local.css. Some configuration is done on special pages in the Site and SiteAdmin? groups, such as the Site.SideBar menu.

The local configuration file (local/config.php)

When you first install PmWiki, the local/config.php file does not exist. Copy the sample-config.php file (in the docs/ directory) to local/config.php and use it as a starting point. You could create local/config.php from scratch, but sample-config.php is already populated with many of the options you might want to adjust.

Here is a simple config.php file:

<?php if (!defined('PmWiki')) exit();
$WikiTitle = "My New Wiki";
$PageLogoUrl = "http://example.com/mylogo.gif";

# Uncomment these if needed
#$ScriptUrl = 'http://example.com/pmwiki/pmwiki.php';
#$PubDirUrl = 'http://example.com/pmwiki/pub';

$DefaultPasswords['admin'] = crypt('onesecret');

$EnableUpload = 1;
$DefaultPasswords['upload'] = crypt('secrettwo');

# Uncomment and change these if needed
# putenv("TZ=EST5EDT"); # if you run PHP 5.0 or older
# date_default_timezone_set('America/New_York'); # if you run PHP 5.1 or newer

$TimeFmt = '%B %d, %Y, at %I:%M %p EST';

Note that config.php begins with <?php . The PHP end tag ?> is optional, and can be left off to improve compatibility with some operating systems. Be sure there aren't any blank lines or spaces before the <?php or after any closing ?>, or else you may get strange PHP error messages at the beginning of your wiki pages.

The config.php file above sets the value of PHP variables used by PmWiki:

  • The $WikiTitle variable gives the name of your site as it will appear in a user's browser title bar.
  • The $ScriptUrl and $PubDirUrl variables tell your wiki where it is located. Often pmwiki can guess, but if you have difficulty with links not working or skins not being found then try uncommenting these lines.
  • The $PageLogoUrl variable specifies the URL of the icon image that will appear in the upper-left corner of each wiki page.
  • The $DefaultPasswords['admin'] sets an administrative password.
  • Setting $EnableUpload to "1" enables Uploads ("Attached files"). $DefaultPasswords['upload'] sets an upload password.
  • The TZ environment variable defines a particular time zone (see Cookbook:ChangeTimeFormat). If your site runs on PHP 5.1 or newer, it is recommended to use the function date_default_timezone_set, see below.
  • The date_default_timezone_set tells PHP what the default time zone is. For other ways to set the time zone, and a list of identifiers, see the online PHP manual.
  • The $TimeFmt variable defines the appearance of time strings and (along with TZ) localizes the wiki to a specific time zone (see Cookbook:ChangeTimeFormat).

By setting these (and other) variables in local/config.php, you can change the look and feel of PmWiki from its default, sometimes substantially so. See PmWiki.Variables for a list of variables that PmWiki uses, and see PmWiki:PmWikiUsers for examples of sites that use PmWiki in customized ways.

Other common setup tasks

The following variables are often requested when preparing a new wiki

These common Cookbook recipes are also often installed immediately

If you prepare an international wiki, potentially with characters in different alphabets (Cyrillic, Greek, Chinese) or many diacritical symbols (Czech + French), please look at PmWiki.UTF-8 and Cookbook:UTF-8.

Security

Review and set up any security required.

Setting an administrative password

The pages in the Site group (except the Site.SideBar) are locked by default. In order to edit pages in this group you need to create a site-wide admin password in local/config.php. To set the site-wide admin password to "mysecret", change the line to the following:

$DefaultPasswords['admin'] = crypt('mysecret');

You must use the crypt() function, but set the password to a value with meaning for you. See PasswordsAdmin for details about making the password more secure.

Don't modify or rename pmwiki.php

PmWiki has been designed so that all customizations can be made without changing the distribution files -- one of its design goals is to provide seamless upgrades. PmWiki never writes to files in the local/ or cookbook/ directories, so placing your customizations here makes it easier to track the changes and upgrade PmWiki without losing the changes.

When changing the configuration of your site, always change the local/config.php file or add files to the cookbook/ or pub directories. Do not change pmwiki.php or the files in the scripts/ directory because the files are supposed to be overwritten upon upgrading.

You shouldn't rename pmwiki.php either. If you rename the file it will not be overwritten during an upgrade of the software and there will be a version mismatch. Many administrators add an index.php "wrapper script" in the pmwiki directory that contains the following single line:

<?php include('pmwiki.php');

Just make an text-file. Paste <?php include('pmwiki.php'); into it. Save the file as index.php Send it via FTP to the same directory as pmwiki.php is located.

Other organisation

Upload directories

By default Pmwiki uses an upload directory for each group (see Uploads administration. Deciding on accepting the default, or choosing an alternative (eg one directory for the entire wiki, or one directory per page) is best done when setting up your wiki.

Page store directories

By default Pmwiki uses a single page store directory (wiki.d). Deciding on accepting the default (recommended), or choosing the alternative (one directory per group) is best done when setting up your wiki. [7]

Other customization

After setting up local/config.php file, you may wish to make other local customizations. See the PmWiki Cookbook for a large number of customizations that have been contributed. And don't fear Cookbook recipes - they're well prepared, so that most of them require only to download a single file, add a one-line include command to config.php, and voilà! - they're working!

If you (or others sharing your server) want to maintain more than one wiki on the same server, see Wiki Farms.

Now what?

Don't forget to join a PmWiki mailing list, where you can email other wiki administrators for help on customizing PmWiki and participate in discussions about PmWiki improvements. Once you have your site operational, be sure to add it to PmWiki:PmWikiUsers so others will know about it!


Upgrades

PmWiki is designed to make it easy to upgrade the PmWiki software without affecting your existing data files or installation. For most upgrades, you simply copy the files in the new release over your existing installation.

Note for PmWiki 1.0 sites: Upgrading from 1.0.x to 2.0 requires more than simply copying the 2.0 software over the 1.0 installation. See Upgrading From PmWiki 1 for more details.

To upgrade PmWiki:

1. Read the release notes

Please read carefully the ReleaseNotes before performing an upgrade, about the changes between your previous version and the new one. See if there are any significant changes or preparation tasks that must be handled before performing the upgrade.

2. Backup

It's always a good idea to have a backup copy of your existing PmWiki installation before starting. You can copy the entire directory containing your existing installation, or you can just make copies of the wiki.d/ directory and any other local customization files you may have created (e.g., config.php, localmap.txt, etc.).

3. Download and extract

Download the version of PmWiki that you want from the download page.

Extract the tar image using tar -xvzf tgzfile, where tgzfile is the tar file you downloaded above. This will create a pmwiki-x.y.z directory with the new version of the software.

4. Copy

Copy the files in pmwiki-x.y.z over the files of your existing PmWiki installation. For example, if your existing PmWiki installation is in a directory called pmwiki, then one way to copy the new files over the existing ones is to enter the command:

cp -a pmwiki-x.y.z/. pmwiki

Note that BSD systems will not have the -a option as a command-line argument for cp, but that's okay, since it's just shorthand for cp -dpR, so use that instead of -a.

Some environments have an alias established for cp that enable interactive prompts before overwriting a file. To work around this specify the absolute path to cp, such as /bin/cp.

On (some) FreeBSD servers and Mac OS X systems you need to use

cp -Rpv pmwiki-x.y.z/. pmwiki

5. Update customisations and recipes

That's it! Your base PmWiki installation is complete.

Now use the PmWiki:Site Analyzer to determine which recipes could be updated to the most recent version.

Unless you have made customizations to the pmwiki.php script or to the files in scripts/, your PmWiki installation should continue to run correctly! (Changes to these files are not recommended).

(Local customizations should go in local/config.php, pub/css, and pub/skins/yourskinname)

Note: Additional tips can be found on the PmWiki:Troubleshooting page.

How can I determine what version of PmWiki I'm running now?

See version - Determining and displaying the current version of PmWiki (pmwiki-2.3.38).

How can I test a new version of PmWiki on my wiki without changing the prior version used by visitors?

The easy way to do this is to install the new version in a separate directory, and for the new version set (in local/config.php):


    $WikiLibDirs = array(&$WikiDir,
      new PageStore('/path/to/existing/wiki.d/{$FullName}'),
      new PageStore('wikilib.d/{$FullName}'));

This lets you test the new version using existing page content without impacting the existing site or risking modification of the pages. (Of course, any recipes or local customizations have to be installed in the new version as well.)

Then, once you're comfortable that the new version seems to work as well as the old, it's safe to upgrade the old version (and one knows of any configuration or page changes that need to be made).


Backup and Restore

This page has some background information on making backups and explains some basic *nix backup and restore procedures.

Introduction

Your wiki installation contains some unique data in the following directories:

    local/         Local configuration scripts
    cookbook/      Recipes obtained from the Cookbook
    pub/           Publicly accessible files
    wiki.d/        Wiki pages
    uploads/       Uploaded files (attachments)

A good backup plan will include periodically archiving these directories — or at bare minimum local/ and wiki.d/. Good practice dictates keeping your backup archives on a separate machine.

Simple Backup and Restore (*nix)

When it comes to backup, simpler is better. Since the pmwiki distribution is very small (about 1/4 megabyte), it's simplest to just archive the distribution files along with the data.

Making a Backup Archive

The following *nix command, executed from the parent directory of your wiki's directory, will put a complete backup archive of your site in your home directory.

tar -zcvf  ~/wiki-backup-`date +%Y%m`.tar.gz  wiki/

Restoring the Backup Archive

Simple Method

Your site can be restored and running in under 30 seconds with

tar -zxvf ~/wiki-backup-200512.tar.gz
find wiki/uploads/ -type d |xargs chmod 777
find wiki/wiki.d/ -type d |xargs chmod 777

A Slightly-More-Secure Method

The simple restore commands above will give you world-writable files and directories. You can avoid world-writable permissions by letting PmWiki create directories with the proper attributes (ownership and permissions) for you.

Start with

tar -zxvf ~/wiki-backup-200512.tar.gz
rm -rf wiki/wiki.d
rm -rf uploads
chmod 2777 wiki/

Now upload a file in each group that had uploads. If your site doesn't have uploads, just visit your site once so the wiki.d/ directory will be created.

Finish your installation with

chmod 755 wiki/
tar -zxvf ~/wiki-backup-200512.tar.gz

Details

The commands on this page assume your site is in a directory called "wiki/". The test backup was made in December, 2005 so it's named accordingly.

Your site will only have an uploads/ directory if uploads are enabled.

The backup command uses a date stamp (YYYYMM) in the filename. If you automate the command via cron you'll wind up with monthly snapshots of your site. You can get a daily snapshot by appending %d to the date command (`date +%Y%m%d` will get you YYYYMMDD). Be wary of space limitations if you have a large uploads/ directory.

See Also

  • A thread [gmane.org] on the pmwiki-users mailing list.
  • A Backup Pages recipe in the cookbook.

Miscellaneous

Backup via FTP

Download and install a ftp client like Filezilla

  1. Using the ftp client connect to the server where you host pmWiki using
    1. the IP address (ex: 123.234.56.67) or the ftp name (ex: ftp.myhost.com)
    2. supply your account name (ex: mylogin) and password (ex: myp4ssw0rd)
  2. Move to your pmWiki directory (ex: /usr/mylogin/web/wiki/ or /tahi/public_html/pmwiki )
  3. Select the folder you want to backup as explained before (probably either only the data or the whole wiki directory)
    • for data you will want to backup both the directories
      • wiki.d for user page data
      • pmwikiuploads (or uploads) for your attachments (uploads)
    • for system you will want, at a minimum, to backup both the directories
      • local for configuration data
      • pub for local CSS and skins customisations
  4. Download them to a local folder
  5. Use 7zip or a similar software to build an archive of this backup

You can also very easily sync your FTP directories with your hard disc via this command line:

wget -nv -np -m ftp://user:password@ftp.yourhost.net/

Download Wget for Windows (other systems normally have it installed).

Alternatively, you can also mirror your FTP directories with lftp:

lftp -u your_user_name,your_password -e "mirror --verbose /wiki.d /path/to/local/folder" ftp://your_host

(this will mirror only the /wiki.d folder, replace with / to mirror everything)

Using rsync

See Cookbook:BackupWithRsync and Cookbook:TwoWayMirroringWithRsync.


Uploads Administration

PmWiki includes a script called upload.php that allows users to upload files to the wiki server using a web browser. Uploaded files (also called attachments) can then be easily accessed using markup within wiki pages. This page describes how to install and configure the upload feature.

Some notes about security

PmWiki takes a somewhat, but justifiable, paranoid stance when it comes to the uploads feature. Thus, the default settings for uploads tend to try to restrict the feature as much as possible:

  • The upload function is disabled by default
  • Even if you enable it, the function is password locked by default
  • Even if you remove the password, you're restricted to uploading files with certain names, extensions, and sizes
  • The characters that may appear in upload filenames are (default) alphanumerics, hyphen, underscore, dot, and space (see also here).
  • The maximum upload size is small (50K by default)

This way the potential damage is limited until/unless the wiki administrator explicitly relaxes the restrictions.

Keep in mind that letting users (anonymously!) upload files to your web server does entail some amount of risk. The upload.php script has been designed to reduce the hazards, but wiki administrators should be aware that the potential for vulnerabilities exist, and that misconfiguration of the upload utility could lead to unwanted consequences.

By default, authorized users are able to overwrite files that have already been uploaded, without the possibility of restoring the previous version of the file. If you want to disallow users from being able to overwrite files that have already been uploaded, add the following line to config.php:

$EnableUploadOverwrite = 0;

Alternatively, an administrator can keep older versions of uploads.

An administrator can also configure PmWiki so the password mechanism controls access to uploaded files.

Basic installation

The upload.php script is automatically included from stdconfig.php if the $EnableUpload variable is true in config.php. In addition, config.php can set the $UploadDir and $UploadUrlFmt variables to specify the local directory where uploaded files should be stored, and the URL that can be used to access that directory. By default, $UploadDir and $UploadUrlFmt assume that uploads will be stored in a directory called uploads/ within the current directory (usually the one containing pmwiki.php). In addition, config.php should also set a default upload password (see PasswordsAdmin).

Thus, a basic config.php for uploads might look like:

<?php if (!defined('PmWiki')) exit();
##  Enable uploads and set a site-wide default upload password.
$EnableUpload = 1;
$DefaultPasswords['upload'] = crypt('secret');

If you have edit passwords and wish to allow all users with edit rights to upload, instead of $DefaultPasswords['upload'], you can set $HandleAuth['upload'] = 'edit'; in config.php.

Important: do NOT create the uploads directory yet! See the next paragraph.

You may also need to explicitly set which filesystem directory will hold uploads and provide a URL that corresponds to that directory like:

$UploadDir = "/home/foobar/public_html/uploads";
$UploadUrlFmt = "http://example.com/~foobar/uploads";

Note: In most installations, you don't need to define or change these variables, usually PmWiki can detect them (and if you do, uploads may simply not work).

Upload directory configuration

Uploads can be configured site-wide, by-group (default), or by-page by changing $UploadPrefixFmt in config.php. This determines whether all uploads go in one directory for the site, an individual directory for each group, or an individual directory for each page. The default is to organize upload by group.
It is recommended that the $UploadPrefixFmt variable defined in config.php is the same for all pages in the wiki, and not different in group or page local configuration files. Otherwise you will be unable to link to attachments in other wikigroups.

Single upload directory

For site-wide uploads, use

$UploadPrefixFmt = '';

Per page upload directories

To organize uploads by page, use:

$UploadPrefixFmt = '/$Group/$Name';

You may prefer uploads attached per-page rather than per-group or per-site if you plan to have many files attached to individual pages. This setting simplifies the management of picture galleries for example. (In a page, you can always link to attachments to other pages.)

The upload directory

For the upload feature to work properly, the directory given by $UploadDir must be writable by the web server process, and it usually must be in a location that is accessible to the web somewhere (e.g., in a subdirectory of public_html). Executing PmWiki with uploads enabled will prompt you with the set of steps required to create the uploads directory on your server (it differs from one server to the next). Note that you are likely to be required to explicitly create writable group- or page-specific subdirectories as well!

Uploading a file

Once the upload feature is enabled, users can access the upload form by adding "?action=upload" to the end of a normal PmWiki URL. The user will be prompted for an upload password similar to the way other pages ask for passwords (see Passwords and PasswordsAdmin for information about setting passwords on pages, groups, and the entire site).

Another way to access the upload form is to insert the markup "Attach:filename.ext" into an existing page, where filename.ext is the name of a new file to be uploaded. When the page is displayed, a '?-link' will be added to the end of the markup to take the author to the upload page. (See Uploads for syntax variations.)

By default, PmWiki will organize the uploaded files into separate subdirectories for each group. This can be changed by modifying the $UploadPrefixFmt variable. See Cookbook:UploadGroups for details.

Versioning Uploaded Files

PmWiki does not manage versioning of uploaded files by default. However, by setting $EnableUploadVersions=1; an administrator can have older versions of uploads preserved in the uploads directory along with the most recent version.

Upload restrictions

Restricting uploaded files for groups and pages

Uploads can be enabled only for specific groups or pages by using a group customization. Simply set $EnableUpload=1; for those groups or pages where uploading is to be enabled; alternately, set $EnableUpload=1; in the config.php file and then set $EnableUpload=0; in the per-group or per-page customization files where uploads are to be disabled.

Restricting total upload size for a group or the whole wiki

Uploads can be restricted to an overall size limit for groups. In the group configuration file (i.e., local/Group.php), add the line

$UploadPrefixQuota = 1000000; # limit group uploads to 1000KB (1MB)

This will limit the total size of uploads for that group to 1000KB --any upload that pushes the total over the limit will be rejected with an error message. This value defaults to zero (unlimited).

Uploads can also be restricted to an overall size limit for all uploads. Add the line

$UploadDirQuota = 10000000; # limit total uploads to 10000KB (10MB)

This will limit the total size of uploads for the whole wiki to 10000KB --any upload that pushes the total over the limit will be rejected with an error message. This value defaults to zero (unlimited).

Restricting uploaded files type and size

The upload script performs a number of verifications on an uploaded file before storing it in the upload directory. The basic verifications are described below.

filenames
the name for the uploaded file can contain only letters, digits, underscores, hyphens, spaces, and periods, and the name must begin and end with a letter or digit.
file extension
only files with approved extensions such as ".gif", ".jpeg", ".doc", etc. are allowed to be uploaded to the web server. This is vitally important for server security, since the web server might attempt to execute or specially process files with extensions like ".php", ".cgi", etc.
file size
By default all uploads are limited to 50K bytes, as specified by the $UploadMaxSize variable. Thus, to limit all uploads to 100KB, simply specify a new value for $UploadMaxSize in config.php:
$UploadMaxSize = 100000;

However, the default maximum file size can also be specified for each type of file uploaded. Thus, an administrator can restrict ".gif" and ".jpeg" files to 20K, ".doc" files to 200K, and all others to the size given by $UploadMaxSize. The $UploadExtSize array is used to determine which file extensions are valid and the maximum upload size (in bytes) for each file type. For example:

$UploadExtSize['gif'] = 20000; # limit .gif files to 20KB

Setting an entry to zero disables file uploads of that type altogether:

$UploadExtSize['zip'] = 0;  # disallow .zip files
$UploadExtSize[''] = 0;     # disallow files with no extension

You can limit which types of files are uploadable by disabling all defaults and specifying only desired types Setting the variable $UploadMaxSize to zero will disable all default file types. Individual file types may then be enabled by setting their maximum size with the variable $UploadExtSize.

# turns off all upload extensions
$UploadMaxSize = 0;

# enable only these file types for uploading
$aSize=100000; // 100 KB file size limitation
$UploadExtSize['jpg' ] = $aSize;
$UploadExtSize['gif' ] = $aSize;
$UploadExtSize['png' ] = $aSize;

Adding new file types to permitted uploads

To add a new extension to the list of allowed upload types, add a line like the following to a local customization file:

$UploadExts['ext'] = 'content-type';

where ext is the extension to be added, and content-type is the "MIME type", or content-type (which you may find here or on the lower part of this page) to be used for files with that extension. For example, to add the 'dxf' extension with a Content-Type of 'image/x-dxf', place the line

$UploadExts['dxf'] = 'image/x-dxf';

Each entry in $UploadExts needs to be the extension and the mime-type associated with that extension, thus:

$UploadExts = array(
  'gif' => 'image/gif',
  'jpeg' => 'image/jpeg',
  'jpg' => 'image/jpeg',
  'png' => 'image/png',
  'xxx' => 'yyyy/zzz'
);

For the types that PmWiki already knows about it's not necessary to repeat them here (the upload.php script adds PmWiki's defaults to whatever the administrator supplies). See also Cookbook:UploadTypes for additional types.

Other file size limits

There are other factors involved that affect upload file sizes. In Apache 2.0, there is a `LimitRequestBody directive that controls the maximum size of anything that is posted (including file uploads). Apache has this defaulted to unlimited size. However, some Linux distributions (e.g., Red Hat Linux) limit postings to 512K so this may need to be changed or increased. (Normally these settings are in an httpd.conf configuration file or in a file in /etc/httpd/conf.d.)

Problem noted on Red Hat 8.0/9.0 with Apache 2.0.x, the error "Requested content-length of 670955 is larger than the configured limit of 524288" was occurring under Apache and a "Page not found" would appear in the browser. Trying the above settings made no change with PHP, but on Red Hat 8.0/9.0 there is an additional PHP config file, /etc/httpd/conf.d/php.conf, and increasing the number on the line "LimitRequestBody 524288" solves the issue.

PHP itself has two limits on file uploads (usually located in /etc/php.ini). The first is the upload_max_filesize parameter, which is set to 2MB by default. The second is post_max_size, which is set to 6MB by default.

With the variables in place--PmWiki's maximum file size, Apache's request-size limits, and the PHP file size parameters, the maximum uploaded file size will be the smallest of the three variables.

Password protecting uploaded files

Setting a read password for pages (and groups) will prevent an attached file from being seen or accessed through the page, but to prevent direct access to the file location (the uploads/ directory) one can do the following:

  • In local/config.php set $EnableDirectDownload=0;
  • If you use per-group upload directories (PmWiki default, see $UploadPrefixFmt), add to config.php $EnableUploadGroupAuth = 1;
  • Deny public access to the uploads/ directory through moving it out of the html/ or public_html/ directory tree, or through a .htaccess file.

See Cookbook:Secure attachments Security issues for attachments

Other notes

  • If uploads doesn't seem to work, make sure that your PHP installation allows uploads. The php.ini file (usually /etc/php.ini or /usr/local/lib/php.ini) should have
file_uploads = On
  • Another source of error in the php.ini file is a not defined upload_tmp_dir. Just set this variable to your temp directory, e.g.
upload_tmp_dir = /tmp

Note that if you change this values, httpd must generally be restarted. Another way to check if uploads are allowed by the server is to set $EnableDiag to 1 in config.php, and set ?action=phpinfo on a URL. The "file_uploads" variable must have a value of 1 (if it says "no value", that means it's off).

How do I disable uploading of a certain type of file?

Here's an example of what to add to your local/config.php file to disable uploading of .zip files, or of files with no extension:

$UploadExtSize['zip'] = 0;  # Disallow uploading .zip files
$UploadExtSize[''] = 0;     # Disallow files with no extension

How do I attach uploads to individual pages or the entire site, instead of organizing them by wiki group?

Use the $UploadPrefixFmt variable (see also the Cookbook:UploadGroups recipe).

$UploadPrefixFmt = '/$FullName'; # per-page, in Group.Name directories
$UploadPrefixFmt = '/$Group/$Name'; # per-page, in Group directories with Name subdirectories
$UploadPrefixFmt = ''; # site-wide

For $UploadDirQuota - can you provide some units and numbers? Is the specification in bytes or bits? What is the number for 100K? 1 Meg? 1 Gig? 1 Terabyte?

Units are in bytes.

   $UploadDirQuota = 100*1024;         # limit uploads to 100KiB
   $UploadDirQuota = 1000*1024;        # limit uploads to 1000KiB
   $UploadDirQuota = 1024*1024;        # limit uploads to 1MiB
   $UploadDirQuota = 25*1024*1024;     # limit uploads to 25MiB
   $UploadDirQuota = 2*1024*1024*1024; # limit uploads to 2GiB

Is there a way to allow file names with Unicode or additional characters?

Yes, see $UploadNameChars

Where is the list of attachments stored?

It is generated on the fly by the

markup.

How can I find orphaned or missing attachments

For older versions of PmWiki, see Cookbook:Attachlist enhanced "How to list missing or orphaned attachments.",
for version 2.2 or higher see Cookbook:Attachtable "Actions to rename, delete & restore deleted attachments, as well as an attachlist replacement to use those actions, show file types and list attachment references."

How can I prevent hotlinking of my uploaded images

See Cookbook:Prevent Hotlinking Prevent hotlinking of uploaded files

I have limited the max upload size to 8 MB in config.php, however only files smaller than 2MB can be uploaded.

Check your php.ini for upload_max_filesize

upload_max_filesize = 8M

If you cannot access your php.ini directly try to soften server limits in the root .htaccess file:

php_value post_max_size 63M
php_value upload_max_filesize 62M
php_value memory_limit 64M
php_value max_execution_time 600
php_value default_socket_timeout 600

How can I upload multiple files at once?

See the following recipes: DragDropMultiUpload, MultiUpload, UploadForm.


Security

Aspects of PmWiki security are found on the following pages:

Pages distributed in a PmWiki release:

  • Passwords General use of passwords and login
  • Passwords Admin More password options for the administrator
  • AuthUser Authorization system that uses usernames and passwords
  • Url Approvals Require approval of Url links
  • Site Analyzer Analyse PmWiki security and software versions
  • Blocklist Blocking IP addresses, phrases, and expressions to counteract spam and vandalism.
  • Notify How to receive email messages whenever pages are changed on the whole wiki site, individual groups or selected watchlists of pages
  • Security variables variables crucial for site security

Pages

How do I report a possible security vulnerability of PmWiki?

Pm wrote about this in a post to pmwiki-users from September 2006. In a nutshell he differentiates two cases:

  1. The possible vulnerability isn't already known publicly: In this case please contact us by private mail.
  2. The possible vulnerability is already known publicly: In this case feel free to discuss the vulnerability in public (e.g. on pmwiki-users or in the PITS).

See his post mentioned above for details and rationals.

What about the botnet security advisory at http://isc.sans.org/diary.php?storyid=1672?

Sites that are running with PHP's register_globals setting set to "On" and versions of PmWiki prior to 2.1.21 may be vulnerable to a botnet exploit that is taking advantage of a bug in PHP. The vulnerability can be closed by turning register_globals off, upgrading to PmWiki 2.1.21 or later, or upgrading to PHP versions 4.4.3 or 5.1.4.
In addition, there is a test at PmWiki:SiteAnalyzer that can be used to determine if your site is vulnerable.

Wiki Vandalism and Spam

Assumptions
you are using a Blocklist and Url approvals.
You don't want to resort to password protecting the entire wiki, that's not the point after all.
Ideally these protections will be invoked in config.php

How do I stop pages being deleted, eg password protect a page from deletion?

Use Cookbook:DeleteAction and password protect the page deletion action by adding $DefaultPasswords['delete'] = '*'; to config.php or password protect the action with $HandleAuth['delete'] = 'edit';

or $HandleAuth['delete'] = 'admin'; to require the edit or admin password respectively.

How do I stop pages being replaced with an empty (all spaces) page?

Add block: /^\s*$/ to your blocklist.

how do I stop pages being completely replaced by an inane comment such as excellent site, great information, where the content cannot be blocked?

Try using the newer automatic blocklists that pull information and IP addresses about known wiki defacers.

(OR) Try using Cookbook:Captchas or Cookbook:Captcha (note these are different).

(OR) Set an edit password, but make it publicly available on the Site.AuthForm template.

How do I password protect the creation of new groups?

See Cookbook:Limit Wiki Groups How to limit the names or number of groups in your wiki

How do I password protect the creation of new pages?

See Cookbook:Limit new pages in Wiki Groups How to limit the creation of new pages in your wiki group

How do I take a whitelist approach where users from known or trusted IP addresses can edit, and others require a password?

Put these lines to local/config.php:

## Allow passwordless editing from own turf, pass for others.
if ($action=='edit'
 && !preg_match("/^90\\.68\\./", $_SERVER['REMOTE_ADDR']) )    
 { $DefaultPasswords['edit'] = crypt('foobar'); }

Replace 90.68. with the preferred network prefix and foobar with the default password for others.

For a single IP, you may use

if($_SERVER['REMOTE_ADDR'] == '127.0.0.1') { # your IP address here
 $_POST['authpw'] = 'xxx';                  # the admin password
}

Please note the security issues : this means that you have your admin passwords in clear in config.php and someone with access to the filesystem can read them (for example a technician of your hosting provider) ; your IP address may change from time to time (unless you have a fixed IP contract with your ISP). When that happens, someone with your old IP address will be logged in automatically as admin on your wiki. It is extremely unlikely to become a problem, but you should know it is possible ; if you are behind a router, all other devices which pass through that router will have the same IP address for PmWiki - your wifi phone, your wife's netbook, a neighbour using your wifi connection, etc. All these people become admins of your wiki. Again, you should evaluate if this is a security risk ; In some cases, your ISP will route your traffic through the same proxy as other people. In such a case, thousands of people may have the same IP address.

See also Cookbook:AuthDNS & Cookbook:PersistentLogin

How do I password protect page actions?

See Passwords for setting in config.php

$HandleAuth['pageactionname'] = 'pageactionname'; # along with :
$DefaultPasswords['pageactionname'] = crypt('secret phrase');

or

$HandleAuth['pageactionname'] = 'anotherpageactionname';

How do I moderate all postings?

Enable PmWiki.Drafts

  • Set $EnableDrafts, this relabels the "Save" button to "Publish" and a "Save draft" button appears.
  • Set $EnablePublishAttr, this adds a new "publish" authorization level to distinguish editing from publishing.

How do I make a read only wiki?

In config.php set an "edit" password.

How do I restrict access to uploaded attachments?

See

How do I hide the IP addresses in the "diff" pages?

If the user fills an author name, the IP address is not displayed. To require an author name, set in config.php such a line:

  $EnablePostAuthorRequired = 1;

The IP address can also be seen in a tooltip title when the mouse cursor is over the author name. To disable the tooltip, set in config.php:

$DiffStartFmt = 
  "<div class='diffbox'><div class='difftime'><a name='diff\$DiffGMT' href='#diff\$DiffGMT'>\$DiffTime</a>
   \$[by] <span class='diffauthor'>\$DiffAuthor</span> - \$DiffChangeSum</div>";

CustomMarkup

Introduction

PmWiki's markup translation engine is handled by a set of rules; each rule searches for a specific pattern in the markup text and replaces it with some replacement text. Internally, this is accomplished by using PHP's "preg_replace" function.

Rules are added to the translation engine via PmWiki's Markup() function, which looks like

Markup($name, $when, $pattern, $replace);

where $name is a unique name (a string) given to the rule, $when says when the rule should be applied relative to other rules, $pattern is the pattern to be searched for in the markup text, and $replace is what the pattern should be replaced with.

For example, here's the code that creates the rule for ''emphasized text'' (in scripts/stdmarkup.php):

Markup("em", "inline", "/''(.*?)''/", "<em>$1</em>");

Basically this statement says to create a rule called "em" to be performed with the other "inline" markups, and the rule replaces any text inside two pairs of single quotes with the same text ($1) surrounded by <em> and </em>.

The first two parameters to Markup() are used to specify the sequence in which rules should be applied. The first parameter provides a name for a rule -- "em" in the example above. We could've chosen other names such as "''", or even "twosinglequotes". In general PmWiki uses the markup itself to name the rule (i.e., PmWiki uses "''" instead of "em"), but to keep this example easier to read later on we'll use a mnemonic name for now.

The second parameter says that this rule is to be done along with the other "inline" markups. PmWiki divides the translation process into a number of phases:

_begin      start of translation
fulltext    translations to be performed on the full text            
split       conversion of the full markup text into lines to be processed
directives  directive processing
inline      inline markups
links       conversion of [[links]], url-links, and WikiWords     
block       block markups
style       style handling       
_end        end of translation

This argument is normally specified as a left-angle bracket ("before") or a right-angle bracket ("after") followed by the name of another rule.

Thus, specifying "inline" for the second parameter says that this rule should be applied when the other "inline" rules are being performed. If we want a rule to be performed with the directives -- i.e., before inline rules are processed, we would specify "directives" or "<inline" for the second parameter.

A significant rule in terms of ordering is "{$var}" which substitutes variables -- if you say "<{$var}" then your markup will be processed before variables are substituted whereas if you say ">{$var}" then your markup will be processed after variables are substituted.

The third parameter is a Perl-compatible regular expression. Basically, it is a slash, a regular expression, another slash, and a set of optional modifiers.

The example uses the pattern string "/''(.*?)''/", which uses ''(.*?)'' as the regular expression and no options. (The regular expression says "find two single quotes in succession, then as few arbitrary characters as are needed to make the match find something, then two additional single quotes in succession"; the parentheses "capture" a part of the wikitext for later use.)

The fourth parameter is the replacement text that should be inserted instead of the marked-up wikitext. You can use $1, $2, etc. to insert the text from the first, second etc. parenthesised part of the regular expression.

In the example, we have "<em>$1</em>", which is an <em>, the text matched by the first parentheses (i.e. by the .*? section of the pattern), and </em>.

Here's a rule for @@monospaced@@ text:

Markup("@@", "inline", "/@@(.*?)@@/", "<code>$1</code>");

and for a [:comment ...:] directive that is simply removed from the output:

Markup("comment", "directives", "/\\[:comment .*?:\\]/", '');

Okay, now how about the rule for '''strong emphasis'''? We have to be a bit careful here, because although this translation should be performed along with other inline markup, we also have to make sure that the rule for ''' is handled before the rule for '', because ''' also contains ''. The second parameter to Markup() can be used to specify the new rule's relationship to any other rule:

Markup("strong", "<em", "/'''(.*?)'''/", "<strong>$1</strong>");

This creates a rule called "strong", and the second parameter "<em" says to be sure that this rule is processed before the "em" rule we defined above. If we wanted to do something after the "em" rule, we would use ">em" instead. Thus, it's possible to add rules at any point in PmWiki's markup translation process in an extensible manner. (In fact, the "inline", "block", "directives", etc., phases above are just placeholder rules used to provide an overall sequence for other rules. Thus one can use "<inline" to specify rules that should be handled before any other inline rules.)

If you want to disable available markup just call e.g.:

DisableMarkup("strong");

PmWiki's default markup rules are defined in the scripts/stdmarkup.php file. To see the entire translation table as the program is running, the scripts/diag.php module adds "?action=ruleset", which displays the set of defined markup rules in the sequence in which they will be processed. You can see it at CustomMarkup?action=ruleset. You must first enable the action by setting $EnableDiag = 1 in your configuration file.

Other common examples

Define a custom markup to produce a specific HTML or Javascript sequence

Suppose an admin wants to have a simple "(:example:)" markup that will always produce a fixed HTML string in the output, such as for a webring, Google AdSense? display, or Javascript. The Markup() call to do this would be:

Markup('example', 'directives',
  '/\\(:example:\\)/',
  Keep("<div class='example'><p>Here is a 
    <a target='_blank' href='http://www.example.com'>link</a> to
    <em>example.com</em></p></div>") );
  • The first argument is a unique name for the markup ("example").
  • The second argument says to perform this markup along with other directives.
  • The third argument is the pattern to look for "(:example:)".
  • The fourth argument is the HTML that "(:example:)" is to be replaced with. We use the Keep() function here to prevent the output from being further processed by PmWiki's markup rule -- in the above example, we don't want the http://www.example.com url to be again converted to a link.

Define a markup to call a custom function that returns content

An 'e' option on the $pattern parameter will cause the $replace parameter to be treated as a PHP expression to be evaluated instead of replacement text. Thus, a markup to produce a random number between 1 and 100 might look like:

Markup('random', 'directives',
  '/\\(:random:\\)/e',
  "rand(1, 100)");

This calls the PHP built-in rand() function and substitutes the directive with the result. Any function can be called, including functions defined in a local customization file.

Arguments can also be passed by using regular expression capturing parentheses, thus

Markup('randomargs', 'directives',
  '/\\(:random (\\d+) (\\d+):\\)/e',
  "rand('$1', '$2')");

will cause the markup (:random 50 100:) to generate a random number between 50 and 100.

Note: Be very careful with the /e modifier in regular expressions; malicious authors may be able to pass strings that cause arbitrary and undesirable PHP functions to be executed.

For a PmWiki function to help with parsing arbitrary sequences of arguments and key=value pairs, see Cookbook:ParseArgs.

How can I embed JavaScript? into a page's output?

There are several ways to do this. The Cookbook:JavaScript recipe describes a simple means for embedding static JavaScript? into web pages using custom markup. For editing JavaScript? directly in wiki pages (which can pose various security risks), see the JavaScript-Editable recipe. For JavaScript? that is to appear in headers or footers of pages, the skin template can be modified directly, or <script> statements can be inserted using the $HTMLHeaderFmt array.

How would I create a markup ((:nodiscussion:)) that will set a page variable ({$HideDiscussion}) which can be used by (:if enabled HideDiscussion:) in .PageActions?

Add the following section of code to your config.php

SDV($HideDiscussion, 0); 	#define var name
Markup('hideDiscussion', '<{$var}',
 '/\\(:nodiscussion:\\)/e', 'setHideDiscussion(true)'); 
function setHideDiscussion($val) { 
  global $HideDiscussion; 
  $HideDiscussion = $val;
} 

This will enable the (:if enabled HideDiscussion:) markup to be used. If you want to print the current value of {$HideDiscussion} (for testing purposes) on the page, you'll also need to add the line:
$FmtPV['$HideDiscussion'] = '$GLOBALS["HideDiscussion"]';

PmWiki only supports tool tips for external links, can I use custom markup to add tool tips to internal links?

Yes, add the following custom markup to your config.php:
Markup('%title%', 'inline', '/%title%(.*?)"(.*?)"(.*?)%%/', '<span title="$2">$1$3</span>'); # Add tool tips to internal links, Example: %title%[[link"tool tip"]]%%

Use the markup with internal links such as:
%title%[[CookBook "cool" | Example]]%%

You can apply it in other situations too, for instance:
%title%"flexible"(:if true:)write something(:else:)write something else(:ifend:)%%

See also Cookbook:LinkTitles.

It appears that (.*?) does not match newlines in these functions, making the above example inoperable if the text to be wrappen in <em> contains new lines.

If you include the "s" modifier on the regular expression then the dot (.) will match newlines. Thus your regular expression will be "/STUFF(.*?)/s". That s at the very end is what you are looking for. If you start getting into multi-line regexes you may be forced to look at the m option as well - let's anchors (^ and $) match not begin/end of strings but also begin/end of lines (i.e., right before/after a newline).

How can the text returned by my markup function be re-processed by the markup engine?

If the result of your markup contains more markup that should be processed, you have two options. First is to select a "when" argument that is processed earlier than the markup in your result. For example, if your markup may return [[links]], your "when" argument could be "<links" and your markup will be processed before the links markup. The second option is to call the PRR() function in your markup definition or inside your markup function. In this case, after your markup is processed, PmWiki will restart all markups from the beginning.

How do I get started writing recipes and creating my own custom markup?

(alternate) Introduction to custom markup for Beginners

How do I make a rule that runs once at the end of all other rule processing?

Use this statement instead of the usual Markup() call:

$MarkupFrameBase['posteval']['myfooter'] = "\$out = onetimerule(\$out);";

CustomWikiStyles

This page describes the predefined Wiki Styles and how a Wiki Administrator can define additional Wiki Styles as a local customization for all pages (in local/config.php) or specific groups (in local/$Group.php).

All predefined Wiki Styles are setup in the global array $WikiStyle. To define your own Wiki Styles, add the setting of the correspondent WikiStyle within the array.

Predefined Wiki Styles

The following array-values are set by scripts/wikistyles.php using the SDV()-function (so you can overwrite them by setting them prior in config.php or farmconfig.php):

markup:definition:

text colors:
(equivalent to %define=xxxx color=xxxx%)
black$WikiStyle['black']['color'] = 'black';
white$WikiStyle['white']['color'] = 'white';
red$WikiStyle['red']['color'] = 'red';
yellow$WikiStyle['yellow']['color'] = 'yellow';
blue$WikiStyle['blue']['color'] = 'blue';
gray$WikiStyle['gray']['color'] = 'gray';
silver$WikiStyle['silver']['color'] = 'silver';
maroon$WikiStyle['maroon']['color'] = 'maroon';
green$WikiStyle['green']['color'] = 'green';
navy$WikiStyle['navy']['color'] = 'navy';
purple$WikiStyle['purple']['color'] = 'purple';

list-styles:
decimal$WikiStyle['decimal']['apply'] = 'list';
$WikiStyle['decimal']['list-style'] = 'decimal';
roman$WikiStyle['roman']['apply'] = 'list';
$WikiStyle['roman']['list-style'] = 'lower-roman';
ROMAN$WikiStyle['ROMAN']['apply'] = 'list';
$WikiStyle['ROMAN']['list-style'] = 'upper-roman';
alpha$WikiStyle['alpha']['apply'] = 'list';
$WikiStyle['alpha']['list-style'] = 'lower-alpha';
ALPHA$WikiStyle['ALPHA']['apply'] = 'list';
$WikiStyle['ALPHA']['list-style'] = 'upper-alpha';

special:
open links in a new browser-window:
newwin$WikiStyle['newwin']['target'] = '_blank';
Turns markup into a comment via display:none CSS
comment$WikiStyle['comment']['display'] = 'none';

wiki styles
frameborder:1px solid #cccccc; padding:4px; background-color:#f9f9f9;
lfloatfloat:left; margin-right:0.5em;
rfloatfloat:right; margin-left:0.5em;
thumb
lframeframe lfloat
rframeframe rfloat
cframe
preblock white-space:pre
sideheadblock class:sidehead

Author-Defined Wiki Styles

  1. The first index of the array defines the style name (e.g. mynewstyle, projectentry etc)
  2. the second index defines the attribute name (e.g. color, background-color, etc.)
  3. the value set defines the attribute value (e.g. red, bold, #00ffcc, etc.)

Sample: If you want to define a (site-wide) style the same as the page style

%define=projectentry color:red%

use

$WikiStyle['projectentry']['color'] = 'red';

The $WikiStyle['projectentry']['apply'] variable may be defined if the wikistyle concerns a particular tag. It may be 'item' (for li|dt), 'list' (for ul|ol|dl), 'div', 'pre', 'img', 'p' or the combining 'block' (for p|div|ul|ol|dl|li|dt|pre|h[1-6]). Example:

 $WikiStyle['top']['apply'] = 'item';
 $WikiStyle['top']['class'] = 'top';

then a markup

 * %top% An important list-item

will output

 <li class="top">An important list-item</li>

Printer-Friendly Styles

If your custom-styles (in local/config.php) are getting very colorful it might be useful to disable them in print-view. This can be done easily by putting them into a condition.

if($action!="print") {
  // your custom-styles
}

Notes

To be done:

Questions:

I tried this but background didn't work, thou border and float worked? /Vincent 2008-04-08

$WikiStyle['vMenu']['background']='#ffffcc' ;
$WikiStyle['vMenu']['float']='left' ;
$WikiStyle['vMenu']['border']='1px dotted red' ;
Try using $WikiStyle['vMenu']['background-color']='#ffffcc'; -- unlike background, background-color is defined in the $WikiStyleCSS array, which is checked for valid properties.

Q: How would i set an image to the left of a paragraph in a WikiStyle? I'd like to provide an icon for paragraphs that are notes, important, warnings, etc.


Internationalizations

PmWiki supports internationalization (internationalisation) of web pages, allowing accented characters to appear in page names and almost complete customization of PmWiki's prompts. Most customization is provided via the XLPage?() function in PmWiki, which loads a set of translation variables from a wiki page (typically named XLPage?, but it can be named anything you wish).

The rest of this page is devoted to the installation, configuration and usage of other language(s) support. If you are looking for tools and help to localize PmWiki in your language, or how you can improve the existing translations, start on pmwiki.org with the page Localization - The Translation Portal.

Loading Translation Pages

Pages for many other languages have already been created and maintained at the pmichaud.com site. You can download an archive of these translations from http://www.pmwiki.org/pub/pmwiki/i18n/ . Simply download the appropriate language archive(s), and unpack the archive(s) into the directory containing your pmwiki.php installation. Each archive contains a number of page files that are placed in your wikilib.d/ directory, and some special scripts for translations that use a character set other than iso-8859-1 (PmWiki's default). You can also use UTF-8 charset.

Once the translation pages are installed, you enable a language by adding a call to XLPage() in your config.php file. For example, to select French language prompts, one would specify

include_once("scripts/xlpage-utf-8.php"); # optional
XLPage('fr','PmWikiFr.XLPage');

which says to load the translations for French ('fr') from the page PmWikiFr.XLPage. The include_once line is recommended if you start a new wiki, and it should be placed before the XLPage? line (for languages with alphabets other than the Latin, the include_once line is required). These lines should be placed near the beginning of config.php, but after any $WikiDir and $WikiLibDirs setting (if you have such setting).

It's possible to load multiple pages; so if you want to create your own local translations without changing the ones you got from an i18n archive, just create another page (see below) and load it first. Be sure that you load first the page with your local changes:

XLPage('fr','PmWikiFr.XLPageLocal');  # my local translations
XLPage('fr','PmWikiFr.XLPage');       # from i18n.tgz

If your intention is to offer multiple languages on your site, and use Wiki Groups as language selectors, you may want to place this code in local customizations files (see Group Customizations). For example, if your site is published in French and English, and the French pages are in a group called Fr, you could create a file named Fr.php in the local/ directory which contains:

<?php if (!defined('PmWiki')) exit();
##change to French language
XLPage('fr','PmWikiFr.XLPage');

You may wish to create a page called PmwikiFr?.php with the same content to access the French documentation in the PmwikiFr? group. En.php is not necessary in this case since English is the default language.

An alternative to the above would be to add to config.php the following, which tests if there is an XLPage? in a group, and if it finds one it gets loaded:

    
$xlpage = FmtPageName('$Group.XLPage', $pagename);
if (PageExists($xlpage)) XLPage($xlpage, $xlpage);

With this method you would need to copy any relevant XLPage? into any group which needs the different language support.

See also Cookbook:MultiLanguage Display content in different languages on a page by user's choice

Creating New Translations

If language pages don't exist for your desired language, it's easy to create one! An XLPage? translation file simply contains lines of the form

'phrase' => 'translated phrase',

where "phrase" is an internationalized phrase (denoted by $[phrase]) in PmWiki's $...Fmt variables, and "translated phrase" is what should be printed in your particular language. For example, the line (in PmWikiFr.XLPage)

'Search' => 'Rechercher',

converts "$[Search]" to "Rechercher" on output. The file Localization:XLPageTemplate is a good starting point for creating a new XLPage? and has most of PmWiki's key phrases already listed in it.

If you create new versions of PmWiki pages in other languages, please consider adding them to the main PmWiki site so that they can be made available to others in the i18n archives! (Be sure to check out The Localization Portal for further information on effectively internationalizing PmWiki.)

The term "i18n" is commonly used as an abbreviation for the English word "internationalization". The abbreviation is derived from the fact that there are 18 letters between the "i" and the final "n" and few people want to type them all out.

Enabling "Special" Characters in WikiLinks?

To enable "special" characters like for example German umlauts in WikiLinks?, it is necessary to configure the server locale to ensure that PmWiki uses the proper character set definition.

If this is not possible due to limited access to the server configuration, PmWiki can be configured to use a specific locale by using the XLPage? options (see XLPageTemplate).

For German umlauts, you'd need for example:

  • 'Locale' => 'deu', <- for Windows servers, see MSDN List of locale identifiers
  • 'Locale' => 'de_DE', <- for Linux servers; for the UTF-8 encoding, on some installations you may need to set 'de_DE.utf8' or 'de_DE.UTF-8'.

Note that the locale identifier depends on the operation system and perhaps on the specific installation.

Notes

If my wiki is internationalized by config.php, how do I revert a specific group to English?

Use $XLLangs = array('en'); in the group's group customization file.

If my wiki is in English and I want just one page, or group, in Spanish do I say XLPage('es','PmWikiEs.XLPage'); in the group or page configuration file?

Yes, that is usually the best method. If you were doing this with many scattered pages, or with several languages, you might find it easier to maintain if you load the translations all in config.php like this:

   XLPage?('es','PmWikiEs.XLPage');
   XLPage?('fr','PmWikiFr.XLPage');
   XLPage?('ru','PmWikiRu.XLPage');
   $XLLangs = array('en');

Then in each group or page configuration file, you'd just use $XLLangs = array('es'); to set the language to use (in this case, Spanish). Note that though this method is easier to maintain, its somewhat slower because it loads all the dictionaries for each page view, even if they won't be used.

What does the first parameter of this function stand for? How can it be used?

The XLPage? mechanism allows multiple sets of translations to be loaded, and the first parameter is used to distinguish them.

For example, suppose I want to have translations for both normal French and "Canadian" French. Rather than maintain two entirely separate sets of pages, I could do:

    XLPage?('fr-ca', 'PmWikiFrCa.XLPage?');
    XLPage?('fr', 'PmWikiFr.XLPage');

PmWikiFr.XLPage would contain all of the standard French translations, while PmWikiFrCA.XLPage? would only need to contain "Canada-specific" translations -- i.e., those that are different from the ones in the French page.

The first parameter distinguishes the two sets of translations. In addition, a config.php script can use the $XLLangs variable to adjust the order of translation, so if there was a group or page where I only wanted the standard French translation, I can set

    $XLLangs = array('fr', 'en');

and PmWiki will use only the 'fr' and 'en' translations (in that order), no matter how many translations have been loaded with XLPage?().

How can I add a translation for an individual string in a PHP file?

Use the XLSDV() function to provide a translation for a specific (English) string. For instance, with this in config.php

    XLSDV('nl', array('my English expression'=>'mijn Nederlandse uitdrukking'));

any instance of the variable expression $[my English expression] in wiki mark-up will be displayed as my English expression in default (English) context, but as mijn Nederlandse uitdrukking in Dutch (nl) context, i.e. when XLPage('nl',...) has been called for that page in config.php or a cookbook recipe.

If you need to get a translation in a PHP file, use the XL() function:

  $local_string = XL("my English expression");

But beware: XLPage?() uses XLSDV() internally for its translation pairs, too, and only the first definition is accepted! Thus, if the Dutch XLPage? already contains a translation and you want to override that, you need to use your XLSDV('nl',...) before calling the correspondent XLPage?('nl',...). Otherwise, by using XLSDV() after XLPage?() - e.g. within a recipe that is included later in config.php - your translation will only work as long nobody defines 'my English expression' in that XLPage?.


LocalCustomizations

A Wiki Administrator can make a lot of customizations simply by setting variables in the /local/config.php and defining cascading style sheets in /pub/css/local.css files. Any group or page can also have its own configuration file and configuration css file.

This page describes how customizations work in general, see PmWiki.Documentation Index for specific customizations that are commonly performed at many PmWiki installations, including:

local/config.php

From its inception, PmWiki has been designed so that Wiki Administrators can greatly customize the way PmWiki displays pages and the markup sequences used to generate pages. (This is even mentioned explicitly in PmWiki Philosophy #4.) As a result, the core pmwiki.php script makes extensive use of PmWiki.Variables to determine how markup sequences will be processed and what each individual page will output.

The simplest type of customization is merely setting a variable to 1 (or TRUE). Here's an example that enables ?action=diag and ?action=phpinfo actions:

$EnableDiag = 1;

You can begin a line with a "#" (an octothorpe, a.k.a. a hash symbol or pound sign) to add a comment. Additionally, some built-in PmWiki variables take values other than 1 or 0 (true or false). Here's another example that customizes the wiki's behavior with respect to search engine web robots (see Cookbook:ControllingWebRobots):

# Remove the default "rel='nofollow'" attribute for external links.
$UrlLinkFmt = "<a class='urllink' href='\$LinkUrl' title='\$LinkAlt'>\$LinkText</a>"

The scripts/ subdirectory (below the directory holding the pmwiki.php script) has many customizations. The PmWiki Cookbook contains many example customizations (recipes) that you can download into the cookbook/ subdirectory, The first few lines of each of these scripts generally contain instructions about how to enable (and use) the feature provided by the script.

These customizations are included in your config.php site configuration. For most scripts this is done by simply adding lines like:

include_once("cookbook/recipefile.php");

and

include_once("scripts/scriptfile.php");

at the end of the config.php file to enable them.

Some of the scripts are automatically enabled for you via the scripts/stdconfig.php script unless you disable it by setting $EnableStdConfig=0; in local/config.php.

Order of the commands in config.php (link)

The following order is recommended:

Note, each part is not required, but if your wiki needs it, this is the recommended order in config.php.

Character encoding of config.php

The encoding used when you save config.php has an effect. Your text editor should allow you to save config.php in the encoding of your wiki. (The default encoding of PmWiki is ISO-8859-1, for new wikis it is recommended to enable UTF-8.)

Newer operating systems like GNU/Linux, FreeBSD? and Apple generally default to saving text files in Unicode/UTF-8; in Windows the default encoding is ANSI/Windows-1252 which is almost the same as PmWiki's ISO-8859-1.

The following free/libre software text editors can edit and save a file in different encodings:

Note that if you use the UTF-8 encoding, you should save your files "without Byte Order Mask (BOM)".

Over time PmWiki will be updated to default to Unicode/UTF-8 encoding, which allows all possible alphabets and languages. See UTF-8 for more information.

pub/css/local.css

You can create this file and set there some custom CSS styles which will override any styles set by skins. For example:

  h1, h2, h3, h4, h5 { color: #880000; } /*dark red titles*/
  a { text-decoration: none; } /* don't underline links */

Don't modify pmwiki.php or other core files

You should strongly resist the temptation to directly modify the pmwiki.php script or the files in the scripts/ subdirectory. Any modifications you make to these files will probably be overwritten whenever you upgrade. Instead, look at some of the sample scripts for examples of customizations that can be performed from config.php. You can even create your own script to do a customization and use include_once(...) to include it from config.php. If you do make your own customization script, you can safely put it in the cookbook/ subdirectory--it won't get overwritten by an upgrade there. You might also want to submit your customization to the pmwiki-users mailing list or the Cookbook so that others can benefit from your effort and so that it can perhaps be included in future releases of PmWiki.

FAQ

There's no "config.php"; it's not even clear what a "local customisation file" is!

The "sample-config.php" file in the "docs" folder, is given as an example. Copy it to the "local" folder and rename it to "config.php". You can then remove the "#" symbols or add other commands shown in the documentation. See also Group Customizations.

Can I change the default page something other than Main.HomePage ($DefaultPage)?

Yes, just set the $DefaultPage variable to the name of the page you want to be the default. You might also look at the $DefaultGroup and $DefaultName configuration variables.

$DefaultPage = 'ABC.StartPage';

How do I get the group / page name in a local configuration file (e.g. local/config.php)?

Use the following markup in pmwiki-2.1.beta21 or newer:

## Get the group and page name
$pagename = ResolvePageName($pagename);
$page = PageVar($pagename, '$FullName');
$group = PageVar($pagename, '$Group');
$name = PageVar($pagename, '$Name');

Note the importance of the order of customizations in config.php above to avoid caching problems.

If you need the verbatim group and page name (from the request) early in config.php, $pagename is guaranteed to be set to

  1. Any value of ?n= if it's set, or
  2. Any value of ?pagename= if it's set, or
  3. The "path info" information from REQUEST_URI (whatever follows SCRIPT_NAME), or
  4. Blank otherwise

according to this posting

Can I remove items from the wikilib.d folder on my site?

The files named Site.* and SiteAdmin?.* contain parts of the interface and the configuration and they should not be removed. The other files named PmWiki* contain the documentation and could be removed.

How do I customize my own 404 error page for non-existent pages?

To change the text of the message, try editing the Site.PageNotFound page.

Is the order of customizations in config.php important? Are there certain things that should come before or after others in that file?

Yes, see Order of the commands in config.php.


GroupCustomizations

One of the purposes of Wiki Groups is to allow a Wiki Administrator to customize the features of PmWiki on a per-group basis. Here is where per group customizations come into play.

  • The local/ subdirectory (typically in $FarmD) is used to hold local configuration files.
  • The pub/css/ subdirectory (typically in $FarmD) is used to hold local css files.

To perform local customizations for a particular WikiGroup,

  • place the customizations in a file called "<groupname>.php" (where <groupname> is the actual name of the page group in question) in the local/ subdirectory
  • place the css customizations in a file called "<groupname>.css" (where <groupname> is the actual name of the page group in question) in the pub/css/ subdirectory.

These files will be automatically processed after processing any local customizations in the config.php and local.css files.

For example, to change the image displayed in the upper-left corner of pages in the "GroupName?" WikiGroup, one could create GroupName?.php containing

<?php
  $PageLogoUrl = "/myimages/chess.gif";

The example's effect would cause all pages in the GroupName? Wiki Group to use "/myimages/chess.gif" as the logo image instead of the default.

To add markup to the beginning or end of each page in a wiki group, see Group headers.

Per-page customizations

PmWiki also allows per-page customizations, simply use the full name of the page to be customized instead of the group. For example, one can use the file local/Chess.HomePage.php to set local customizations for Chess.HomePage.

Almost any customization that would be placed in config.php can be used as a per-group or per-page customization.

An important exception to this is setting per-group or per-page customizations for recipe scripts included in config.php. Most recipe scripts would need any customization variables defined before the script is included. Instead of using a per-group or per-page customization php file, use a per-group or per-page conditional statement in config.php, before including the recipe script. Example:

$page = PageVar($pagename, '$FullName');
$group = PageVar($pagename, '$Group');
//per-group customizations:
if($group=='GroupName') {
   $RecipeVariable = 'valueA';
   etc. ...
}
//per-page customizations:
if($page=='GroupName.PageName) {
   $RecipeVariable = 'valueB';
   etc. ...
}
//include recipe after variables are set:
include_once('cookbook/recipescript.php');

Note that this method cannot be used to set $DefaultPasswords, you should use Group or Page attributes. See Passwords and PasswordsAdmin for more information.

Processing order

For all local customizations, PmWiki first processes the local/config.php file, and then looks for a per-page customization file in the local/ subdirectory to process, followed by any per-group customization file. If no per-page or per-group customizations are loaded, then PmWiki loads local/default.php. If a per-page customization wants to have the per-group customizations loaded first, it can do so directly by using PHP's include_once() function. For more information see wiki cascades.

Custom CSS styles per group or per-page

To apply CSS styles to pages of a specific group named Group Name?, create a file named GroupName?.css in the pub/css/ directory and add the CSS style rules there. To apply styles to a specific page, create a file GroupName.PageName?.css in this directory with your style rules. Any CSS rules to be applied for all wiki pages can be put into pub/css/local.css.

/pub/css/GroupName.css:

  body { background: #F4C4B4; }

Preventing group-Level configurations

Any customization file can set $EnablePGCust=0; to prevent later page/group/default customizations from being automatically loaded. If a per-page customization needs to have the per-group customizations loaded first, it can do so directly by using PHP's include_once() function.

Authentication

Any passwords required for a group should be set in the group's Group Attributes page (see Passwords Administration) and not in a group customization file.

Consider Wiki Farms

Wiki Groups are an easy way to host multiple sites in a single PmWiki installation by giving each site its own group. Another approach is to use Wiki Farms, which allows each site to have its own set of Wiki Group and local customization files. Read about

If you are looking for nested group levels, you may want to consider Pm's design considerations on hierarchical groups.

How can I apply CSS styles to a particular group or page?

Simply create a pub/css/Group.css or pub/css/Group.Page.css file containing the custom CSS styles for that group or page.

Why shouldn't passwords be set in group (or page) customization files? Why shouldn't group or page passwords be set in config.php?

The reason for this advice is that per-group customization files are only loaded for the current page. So, if $DefaultPasswords['read'] is set in GroupA?.php, then someone could use a page in another group to view the contents of pages in GroupA?. For example, Main.WikiSandbox could contain:

(:include GroupA.SomePage:)

and because the GroupA?.php file wasn't loaded (we're looking at Main.WikiSandbox --> local/Main.php), there's no read password set.

The same is true for page customization files.

Isn't that processing order strange? Why not load per page configuration last (that is after global configuration an per group configuration)?

Many times what we want to do is to enable a certain capability for a group of pages, but disable it on a specific page, as if it was never enabled. If the per-group config file is processed first, then it becomes very difficult/tedious for the per-page one to "undo" the effects of the per-group page. So, we load the per-page file before the per-group.

If a per-page customization wants the per-group customizations to be performed first, it can use the techniques given in PmWiki.GroupCustomizations (using include_once() or setting $EnablePGCust = 0).


Skins

What's a skin?

A skin changes the look and feel of a PmWiki page, Group of pages, or the entire wiki. To see this try some skins out using the links below.

As you see, all skins show the same page contents, but the other elements such as the sidebar, header, and footer, have changed. For example, different skins may display the sidebar on the left, on the right, or even not at all. Some skins have action links and features that others do not, especially if they were designed to take advantage of particular cookbook recipes.

So, a skin is just the set of files that determine how pages are displayed in PmWiki. Skins are stored as subfolders of pub/skins/. For example you might create the example skin in pub/skins/example/. Each skin typically has one or more of the following kinds of files:

  • A template file, such as skin.tmpl or example.tmpl. The template is written in HTML or XHTML, and is the skeleton for the skin. It contains special markers that tell PmWiki where to insert the page's contents.
  • CSS stylesheet files, which can control the skin's appearance, such as pmwiki.css or example.css.
  • Image files, for decorating a page with images.
  • PHP files, such as skin.php or example.php. These let skins provide extra customization setting or capabilities that HTML and CSS alone cannot.
  • Documentation files for the administrator, usually with names like readme.txt, install.txt or skinname.txt. These usually give you information about any special installation steps or nifty features the skin has.

Where do I get skins?

Skins are available in the Skins:Skins collection. The skins in the collection have been contributed by many PmWiki administrators for all to use, and typically have their own set of customization possibilities. When you find a skin you like, follow the link to download the skin package. You can also make your own skin.

How do I use or install a skin?

Most skin packages are .zip, .tgz, or .tar.gz files. You should be able to unpack these with most archiving software.

  1. Unpack the skin to pub/skins/ inside your pmwiki folder. Most well-designed skin packages will create a subfolder in pub/skins/ named after the skin.
    • If the skin did not make a folder of its own, create one and move the skin files to it.
  2. Open up your local/config.php file, and add a line like
$Skin = 'example';

where example is the name of the skin's folder.

Reload a page from your wiki in the browser, and you should be able to see the difference.

If you'd like to let your site's visitors choose one skin from a selection of skins you've installed, look at the Skins:Skin Change recipe. (That's what we used for the demo above.)

How can I modify an existing skin?

There are a number of ways to further customize the appearance of a skin, including

  • adding statements to /local/config.php that are compatible with your chosen skin;
  • adding css files to /pub/css/, such as local.css (for your entire wiki) and MyGroup?.css (for MyGroup?); and
  • directly editing the skin's files.

If the skin is updated regularly, you probably will want to avoid editing the files in the skin's folder. Check the skin's page in the Cookbook for specific suggestions.

If you want to modify the default pmwiki or print skins included with the PmWiki distribution, you should copy the pub/skins/pmwiki/ and pub/skins/print/ directories to another name and then use those skins instead of the default ones. While the name of the skin.tmpl and skin.css files don't usually matter, the optional skin.php file MUST match the name of the skin.

How can I make a skin?

The best way to make your first skin is to modify a copy of PmWiki's default skin.

  1. Make a copy of the folder pub/skins/pmwiki and name it whatever your new skin should be named.
  2. In your local/config.php file, set $Skin to be the name of your new skin.
  3. Modify the template and CSS files to suit you.
  4. Test your new skin.
  5. Repeat steps 3 and 4 until you're happy with the results.

The reason we recommend starting with the default PmWiki skin is that it's quite a simple skin, much more so than many of the skins you'll find in Skins:Skins. The starting point is the template (.tmpl) file, which provides the overall layout of the page. Inside of the template file are a number of special substitutions and directives that provide places for PmWiki to insert the data relevant to the current page being displayed. Skin Templates describes the format and directives in more detail. There are also skin guidelines available on pmwiki.org.

It's beyond the scope of this page to explain how to write HTML (hypertext markup language), XHTML (extensible HTML, which is a bit newer) or CSS (cascading style sheets), but there are many good tutorials on the web for all three of them. One caution: if you run into an HTML tutorial that explains about how to use <font> or <blink> tags, or spacer gifs, it's at least five years out of date, so skip it and find another one.

You should test your skin on a variety of browsers -- ideally as many as you can, on as many different platforms as you can -- but at minimum you should be testing on Internet Explorer 8, Firefox 3, and Chrome, since those are the most common, and have different bugs, it is also useful to test on Opera and Safari. Don't forget to do things like resize windows and change text size during your testing.

Print Skins

By default your new skin will use the standard /pub/skins/print/ skin.

To over-ride this add the following to local/config.php:

$ActionSkin['print'] = 'yourprintskin';

This says to use 'yourprintskin' for ?action=print instead of the default.

Tools that you'll need

There are good examples of all these programs available for free.

HTML and CSS editor(s). There are two types of editors: graphical (WYSIWYG, or "what you see is what you get"), and hand-coding or programmer's editors. Graphical editors are less intimidating to novices, but you won't learn as much, or know your code as intimately as you will by using a hand-coding editor. Whichever you choose, get one that has syntax highlighting for the code, because it will help you spot mistakes. Also, live preview features are not that helpful when writing a PmWiki skin, because PmWiki does stuff that the live preview won't, such as substitute values for variables and insert sidebar content.

Test wiki. You don't want to be wreaking havoc on your skin while visitors can see your site. It's a better idea to set up a test wiki, either on your real webserver or on your own machine. Linux or MacOS computer owners may have webservers and PHP already running on their machines, but Windows users often don't. If that describes you, then you might want to take a look at the Cookbook:Standalone recipe, which runs PmWiki without needing a complex webserver, or Cookbook:InstallOnIIS. Or, you can find many local server packages which install a webserver, PHP, and other stuff (e.g. MySQL), all configured to work together. Try to get a package that has the same software and versions as used on your live setup, since then there will be less to go wrong when the site goes live.

FTP client to transfer files to your webserver. You probably had one of these already.

Color picker. Your editor might include one, or you could pick up a standalone application. Extremely helpful for creating and saving color palettes.

See also

How do I change the Wiki's default name in the upper left corner of the Main Page?

Put the following config.php

$WikiTitle = 'My Wiki Site';

The docs/sample-config.php file has an example of changing the title.

How can I embed PmWiki pages inside a web page?

Source them through a PHP page, or place them in a frame.

How do I change the font or background color of the hints block on the Edit Page?

Add a CSS style to pub/css/local.css: .quickref {background:...; color:... }. The hints are provided by the Site.EditQuickReference page, which is in the PmWiki or Site wikigroup. Edit that page, and change the "bgcolor" or specify the font "color" to get the contrast you need.


SkinTemplates

This page describes the skin template files (.tmpl) that are used to create PmWiki skins, and how PmWiki uses them. As described in the skins page, a skin is a collection of files that specifies the layout for PmWiki pages. Each skin must include a template file that provides the skeleton for displaying a PmWiki page.

Finding and Processing Templates

When you set the value of the $Skin variable in a configuration file like local/config.php, like this

## Use the Foo Skin.
$Skin = 'foo';

it tells PmWiki to search for a skin of that name, and use it. The usual result of the search is for PmWiki to load a template file from the appropriate skin directory. In this example, that would probably be the file pub/skins/foo/foo.tmpl.

The actual processing that PmWiki goes through to find a template file is important for those who are making complex skins, so its worth mentioning what those steps are:

Security Note

The default value for $SkinLibDirs? has server-side and client-side files stored in the same publicly-accessible directory. That is, $SkinDir and $SkinDirUrl point to the same place. This is done for convenience (both for the skin user, and the skin writer), but it is not necessary.

It has the side effect that its possible to construct a URL (like this one) that will let you look at the contents of the the .tmpl or .php files that a skin uses. This is usually not an issue as skin files should not contain any sensitive information.

Still, a purist might want to move their .tmpl and .php files out of the directories that are accessible as URLs?, and modify their $SkinLibDirs? array to reflect this.

  1. When $PageTemplateFmt is blank (as it should be), PmWiki gathers the names of all candidate skins. It starts with any action-specific skin that is specified in $ActionSkin[$action]. Thus, if the current action is 'login', and $ActionSkin['login'] is 'Bar', then PmWiki will look for a skin named 'Bar'.
  2. If no skin has been found yet, it looks for the skin(s) named in the $Skin variable (which is allowed to be an array) and uses the first skin it can find. If it gets to the end of the list without finding a skin, it issues an error.
  3. To attempt to find a skin, PmWiki first consults the $SkinLibDirs variable to know where to look. Skins consist of server-side files that are loaded by PmWiki (such as .php and .tmpl files) and client-side files (such as .css files and images) that will be requested by the user's browser when they look at a skinned PmWiki page. $SkinLibDirs is an array of key/value pairs. The key is a directory to look in for the server-side files, while the corresponding value is a URL that points to the public client-side resources used by the skin. The default value of $SkinLibDirs? is:
    $SkinLibDirs = array(
       "./pub/skins/\$Skin"      => "$PubDirUrl/skins/\$Skin",
       "$FarmD/pub/skins/\$Skin" => "$FarmPubDirUrl/skins/\$Skin");
    
    So, using the above definitions, PmWiki would try to find the skin 'foo' by looking for a directory called ./pub/skins/foo and then for $FarmD/pub/skins/foo (with the value of $FarmD replaced by the root server directory for Farm files). The first such directory that was found would be assumed to contain the skin it was looking for. It would then set $SkinDir to the name of this directory and $SkinDirUrl to the corresponding URL.
  4. Once a valid skin directory has been found, PmWiki starts processing the files in that directory, looking for a .php skin file to run. It first looks for one with the same name as the skin. So, if the skin is 'foo', it looks for foo.php. If no such file is found, it then checks for a file named skin.php. If one of these .php files is found, PmWiki loads and runs it. This allows a skin to define custom markup, or custom configuration parameters. It also allows a skin to choose between which of several different .tmpl files to load.
    To specify which .tmpl file to load, simply call LoadPageTemplate?() inside the skin .php file, with the name of the .tmpl file to be loaded:
    For example, a skin might specify a special template to be used if the action is 'print':
    if ($GLOBALS['action'] == 'print')
      LoadPageTemplate($pagename, "$SkinDir/print.tmpl");
    
    When the action is something else, PmWiki will fall back to loading the default .tmpl file instead.
  5. If no appropriate .php file is found, or if that file doesn't load a template, then PmWiki falls back to looking for a template with the same name as the skin, or, failing that, any .tmpl file at all, so long as its the only one in the directory. If it finds one, it will load and process it. If not, it will issue an error.

Template file format

A template file is basically an HTML file that also contains variable substitutions (indicated by '$') and special directives embedded in HTML comments. The following special directives are required in the template file.

  1. The directive <!--PageText--> belongs to the <body> section of the HTML document, and tells PmWiki where the main content of each wiki page should be placed.
  2. The directive <!--HTMLHeader-->, which goes somewhere in the <head> section of the HTML document.
  3. The directive <!--HTMLFooter--> directive, which typically goes before the final </body> tag and is used by some recipes to insert things at the end of the HTML document. Prior to PmWiki 2.2.0 the <!--HTMLFooter--> directive was optional.

When PmWiki displays a page, it replaces the directives and variable substitutions with the values appropriate to the current page. For example, the <!--PageText--> directive is replaced with the page's contents, while any instances of $PageUrl are replaced with the url (address) of the current page.

There is a long list of variables available for substitution in pages; some of the most useful include:

$PageUrl         the url of the current page
$ScriptUrl       the base url to the pmwiki.php script
$Title           the page's title (e.g., "`SkinTemplates")
$Titlespaced     the page's title with spaces (e.g., "Skin Templates")
$Group           the name of the current group  (e.g., "`PmWiki")
$FullName        the page's full name (e.g., "`PmWiki.SkinTemplates")
$LastModified    the page's last modification time
$PageLogoUrl     the url of a site logo
$WikiTitle       the site's title
$SkinDirUrl      the url of the skin's folder

This last variable, $SkinDirUrl, is particularly useful in templates as it allows the skin designer to refer to other files (such as images or style sheets) in the skin folder without having to know the exact url.

The template is not limited to using the variables listed here; nearly any PHP global variable that begins with a capital letter can be used in a skin template. Page variables can also be used in templates.

Skin directives

Besides the required <!--PageText--> and <!--HTMLHeader--> directives, PmWiki provides other built-in directives for generating page output. It's not necessary to use any of these directives, but they can often add capabilities to a skin

<!--wiki:Main.SomePage-->
<!--page:Main.SomePage-->
The <!--wiki:Main.SomePage--> directive outputs the contents of Main.SomePage. $-substitutions are allowed in directives, thus a directive like <!--wiki:$Group.SomePage--> will include "SomePage" of the current group.
If multiple pages are listed in the directive, then only the first available page is used. Thus <!--wiki:$Group.SomePage Site.SomePage--> will display the contents of SomePage in the current group if it exists, and Site.SomePage if it doesn't. To always display Site.SomePage, even if $Group.SomePage exists, use two consecutive <!--wiki:...--> directives.
The <!--wiki:...--> directive only displays pages for which the browser has read permissions. The <!--page:...--> directive displays pages even if the browser doesn't have read permission.
<!--file:somefile.txt-->
The directive <!--file:somefile.txt--> outputs the contents of another file (on the local filesystem) at the point of the directive. If the file to be included is a .php script, then the PHP script is executed and its output is sent to the browser. Like the <!--wiki:...--> directive above, $-substitutions are available to be able to output files based on the current page name or group.
<!--markup:...-->
The markup directive processes any text that follows the colon as wiki markup and displays that in the output.
<!--function:SomeFunction args-->
This directive calls a PHP function named "SomeFunction", passing the current page's name and the text following the function name as arguments. PHP functions called in this manner are typically defined in a local customization file. Args allows only one argument, which has to be splitted then. <!--function:SomeFunction arg1 arg2 arg3--> generates one parameter "arg1 arg2 arg3". However variables can be used (like $LastModifiedBy).

Page sections

A template file can designate "sections" that are included or excluded from the output based on page directives or other criteria. A section always begins with <!--Page...Fmt--> and continues to the next section, the end of the template file, or <!--/Page...Fmt-->. For example, a template can specify a <!--PageLeftFmt--> section that is excluded from the output whenever the (:noleft:) directive is encountered in the page's contents. PmWiki's predefined sections (and their corresponding page directives) are:

<!--PageHeaderFmt-->          (:noheader:)
<!--PageFooterFmt-->          (:nofooter:)
<!--PageTitleFmt-->           (:notitle:)
<!--PageLeftFmt-->            (:noleft:)
<!--PageRightFmt-->           (:noright:)
<!--PageActionFmt-->          (:noaction:)

Skin designers can define custom sections and markups, but currently all section names in the template must begin with "Page" and end with "Fmt". As mentioned you also have to define the corresponding markup (for example in your config.php) like this:

Markup('noxyz', 'directives',  '/\\(:noxyz:\\)/ei',
    "SetTmplDisplay('PageXYZFmt',0)");

Internationalization (i18n)

Skins can also be internationalized by using $[...] substitutions. Any string placed inside of $[...] is treated as a "translatable phrase", and the phrase is looked up in the current translation tables for a corresponding output phrase. If a translation is available, then the translated phrase is substituted at that point, otherwise the original phrase is left intact.

For example, the substitution $[Edit] will display the current translation of "Edit" if it is known, otherwise it displays "Edit". Thus, the same template can be used for multiple languages, displaying "Editer" when French translations are loaded, "Bearbeiten" when German translations are loaded, and "Edit" when no translation is available.

How do I customize the CSS styling of my PmWiki layout?

See Skins for how to change the default PmWiki skin. See also Skins?, where you will find pre-made templates you can use to customize the appearance of your site. You can also create a file called local.css in the pub/css/ directory and add CSS selectors there (this file gets automatically loaded if it exists). Or, styles can be added directly into a local customization file by using something like:

$HTMLStylesFmt[] = '.foo { color:blue; }';

Where can the mentioned "translation table" be found for adding translated phrases?

See Internationalizations.

Is it possible to have the edit form in full page width, with no sidebar?

If the sidebar is marked with <!--PageLeftFmt-->, adding (:noleft:) to Site.EditForm will hide it when a page is edited.

Can I easily hide the Home Page title from the homepage?

Yes, you can use in the wiki page either (:title Some other title:) to change it or (:notitle:) to hide it.

Is it possible to hide the Search-Bar in the default PmWiki Skin?

Yes, please see Cookbook:HideSearchBar.


SitePreferences

The page Site.Preferences contains customisable browser preference settings. These include access keys (keyboard shortcuts to certain actions like edit, history, browse) and settings of the Site.EditForm (width and height of the edit textarea) as well as the name of the edit form in use.

A different page than Site.Preferences can be chosen by making a copy of that page under a new name, customising it, and setting a cookie which will point to this page for the browser being used, through

   ?setprefs=SomeGroup.CustomPreferences 

SomeGroup.CustomPreferences being the name of the new customised preference page.

Notes and Comments

Note that in order to enable parsing of Site.Preferences by default, a line like the following needs to be added to local/config.php:

 XLPage?('prefs', "Site.Preferences");

WebFeeds

Web feeds are a convenient mechanism to let visitors be notified of changes to a site. Instead of repeatedly checking RecentChanges every day to see what is new, a visitor can use a news aggregator to quickly see what pages of interest have changed on a site. Web feeds are commonly recognized by terms such as RSS, Atom, and web syndication. They are also the foundation for podcasting.

In its simplest form, web feeds in PmWiki are built on WikiTrails. Using a feed action such as ?action=rss or ?action=atom on a trail generates a web feed (often called a "channel") where each page on the trail is an item in the feed. Since the RecentChanges and Site.AllRecentChanges pages are effectively trails, one can easily get an RSS feed for a group or site by simply adding ?action=rss to the url for a RecentChanges page. For example, to get the site feed for pmwiki.org, one would use

Authors can also create custom feeds by simply creating a wiki trail of the pages they want included in the feed. Feeds can also be generated from groups, categories, and backlinks, and the order and number of items in the feed can be changed using options in the feed url. Thus, one can obtain a feed for the Skins category (sorted with most recent items first) by using

PmWiki is able to generate feeds in many formats, including RSS 2.0 (?action=rss), Atom 1.0 (?action=atom), and RSS 1.0 (?action=rdf). In addition, although it is not normally considered a web feed, PmWiki can generate metadata information using the Dublin Core Metadata extensions (?action=dc).

How to read a PmWiki syndicated feed

  1. You'll need a news aggregator, which is a piece of software designed to read news feeds. Many different news aggregators are available. Some run on your own computer, either on their own or as plugins for email clients, web browsers, or newsreaders. Others are web applications that you can use from any Internet-connected computer. Some are in between (technically web applications, but ones designed to run on your computer, not some remote server). Get one that you like.
  2. Subscribe to the WikiTrail you desire by supplying the feed url to the aggregator. The feed url will be the name of a trail page with ?action=rss or ?action=atom added to the end of the url.

Feed options

Add any of the following options to the end of a PmWiki web feed url to change its output (basically any pagelist option is available for web feeds):

?count=n
Limit feed to n items (default 10)
?order=-time
Display most recently changed items first (default: the order of the trail, or by name; in RecentChanges pages the trail is already ordered by -time)
?trail=page
Obtain items from trail on page (default: the trail on the current page)
?group=group
Limit feed to pages in group
?name=name
Limit feed to pages with specific name
?link=page
Create feed from pages linked to page
?list=normal
Exclude things like RecentChanges, AllRecentChanges?, etc.

authors (intermediate)

Configure PmWiki for feeds

This section describes how to syndicate portions of a wiki to appear in a web feed. It does not describe how to display a web feed within a wiki page -- for that, see Cookbook:RssFeedDisplay.

To enable web feed generation for a site, add one or more of the following to a local customization file:

if ($action == 'rss') include_once("$FarmD/scripts/feeds.php");
if ($action == 'atom') include_once("$FarmD/scripts/feeds.php");
if ($action == 'rdf') include_once("$FarmD/scripts/feeds.php");
if ($action == 'dc') include_once("$FarmD/scripts/feeds.php");

or you can combine multiple feeds into a single expression using "||" to separate each feed type. For example, if you want to enable RSS and Atom feeds you would use

if ($action == 'rss'  ||
    $action == 'atom' ||
    $action == 'rdf'  ||
    $action == 'dc') include_once("$FarmD/scripts/feeds.php");

Configure feed content

Web feeds are highly configurable, new elements can be easily added to feeds via the $FeedFmt array. Elements in $FeedFmt look like

$FeedFmt['atom']['feed']['rights'] = 'All Rights Reserved';

where the first index corresponds to the action (?action=atom), the second index indicates a per-feed or per-item element, and the third index is the name of the element being generated. The above setting would therefore generate a "<rights>All Rights Reserved</rights>" in the feed for ?action=atom.

If the value of an entry begins with a '<', then feeds.php doesn't automatically add the tag around it. Elements can also be callable functions which are called to generate the appropriate output. See RSS specification or other feed specifications for what feed content you can use.

You can also change an existing element rather than add a new one. You can use the following lines to ensure that changes made to the wiki will be picked up by some RSS readers that wouldn't otherwise "notice" a page has been changed:

# Change the link URL when an item is edited.
$FeedFmt['rss']['item']['link'] = '{$PageUrl}?when=$ItemISOTime';
$FeedFmt['atom']['item']['link'] =
   "<link rel=\"alternate\" href=\"{\$PageUrl}?when=\$ItemISOTime\" />\n";

See Also

How do I include text from the page (whole page, or first X characters) in the feed body? (note: markup NOT digested)

    function MarkupExcerpt?($pagename) {
      $page = RetrieveAuthPage?($pagename, 'read', false);
      return substr(@$page['text'], 0, 200);
    }

    $FmtPV['$MarkupExcerpt'] = 'MarkupExcerpt?($pn)';
    $FeedFmt['rss']['item']['description'] = '$MarkupExcerpt';

Q:Does this mean if I want to include the time in the rss title and "summary" to rss body I call $FeedFmt twice like so:

$FeedFmt['rss']['item']['description'] = '$LastSummary'; 
$FeedFmt['rss']['item']['title'] = '{$Group} / {$Title} @ $ItemISOTime';
From mailing list Feb 13,2007, a response by Pm: Yes

How can I use the RSS <enclosure> tag for podcasting?

For podcasting of mp3 files, simply attach an mp3 file to the page with the same name as the page (i.e., for a page named Podcast.Episode4, one would attach to that page a file named "Episode4.mp3"). The file is automatically picked up by ?action=rss and used as an enclosure.

The set of potential enclosures is given by the $RSSEnclosureFmt array, thus

$RSSEnclosureFmt = array('{$Name}.mp3', '{$Name}.wma', '{$Name}.ogg');

allows podcasting in mp3, wma, and ogg formats.

How to add "summary" to the title in a rss feed (ie. with ?action=rss)?

Add this line in you local/config.php

$FeedFmt['rss']['item']['title'] = '{$Group} / {$Title} : $LastModifiedSummary';

How to add "description" to the title in an rss feed, and summary to the body?

Add these lines to your local/config.php

$FeedFmt['rss']['item']['title'] = '{$Group} / {$Title} : {$Description}';
$FeedFmt['rss']['item']['description'] = '$LastModifiedSummary';

NOTES:

  • you need to replicate these lines for each type (atom, rdf, dc) of feed you provide.
  • the RSS description-tag is not equivalent to the pmWiki $Description variable, despite the confusing similarity.

Some of my password-protected pages aren't appearing in the feed... how do I work around this?

From a similar question on the newsgroup, Pm's reply:

The last time I checked, RSS and other syndication protocols didn't really have a well-established interface or mechanism for performing access control (i.e., authentication). As far as I know this is still the case.

PmWiki's WebFeeds capability is built on top of pagelists, so it could simply be that the $EnablePageListProtect option is preventing the updated pages from appearing in the feed. You might try setting $EnablePageListProtect=0; and see if the password-protected pages start appearing in the RSS feed.

The "downside" to setting $EnablePageListProtect to zero is that anyone doing a search on your site will see the existence of the pages in the locked section. They won't be able to read any of them, but they'll know they are there!

You could also set $EnablePageListProtect to zero only if ?action=rss:

    if ($action == 'rss') $EnablePageListProtect = 0;

This limits the ability to see the protected pages to RSS feeds; normal pagelists and searches wouldn't see them.

Lastly, it's also possible to configure the webfeeds to obtain the authentication information from the url directly, as in:

    .../AllRecentChanges?action=rss&authpw=secret

The big downside to this is that the cleartext password will end up traveling across the net with every RSS request, and may end up being recorded in Apache's access logs.

How to add feed image?

Add the following to local/config.php (this example is for ?action=rss):

$FeedFmt['rss']['feed']['image'] =
" <title>Logo title</title>
 <link>http://example.com/</link>
 <url>http://example.com/images/logo.gif</url>
 <width>120</width>
 <height>60</height>";
Do not forget NOT to start with a '<' as there would be no <image> tag around this... See here.

How do I insert RSS news feeds into PmWiki pages?

See Cookbook:RssFeedDisplay.

How can I specify default feed options in a configuration file instead of always placing them in the url?

For example, if you want ?action=rss to default to ?action=rss&group=News&order=-time&count=10, try the following in a local customization file:

   if ($action == 'rss')
     SDVA($_REQUEST, array(
       'group' => 'News',
       'order' => '-time',
       'count' => 10));

Are there ways to let people easily subscribe to a feed?

On some browsers (Mozilla Firefox), the visitor can see an orange RSS icon in the address bar, and subscribe to the feed by clicking on it. To enable the RSS icon, add this to config.php :

$HTMLHeaderFmt['feedlinks'] = '<link rel="alternate" type="application/rss+xml" 
  title="$WikiTitle" href="$ScriptUrl?n=Site.AllRecentChanges&amp;action=rss" />
<link rel="alternate" type="application/atom+xml" title="$WikiTitle"
  href="$ScriptUrl?n=Site.AllRecentChanges&amp;action=atom" />';

You can also add such a link, for example in your SideBar, [[Site.AllRecentChanges?action=atom | Subscribe to feed]].

Can I create an RSS feed for individual page histories?

See Cookbook:PageFeed.

How do I create a custom FeedPage? similar to RecentChanges or AllRecentChanges?, but with only certain groups or pages recorded?

See Cookbook:CustomRecentChanges. In a nutshell, you'll declare a $RecentChangesFmt variable with your dedicated FeedPage?, and then wrap it in a condition of your choice. For example:

   if (PageVar($pagename, '$Group')!='ForbiddenGroup') {
     $RecentChangesFmt['Site.MyFeedPage'] =
       '* [[{$FullName}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]';
   }

How can I update my RSS feed to show every edit for pages on that feed, not just new pages added to the feed?

Add unique guid links for each edit to your to congif.php file (see PITS entry):

   $FeedFmt['rss']['item']['guid'] = '{$PageUrl}?guid=$ItemISOTime';

Alternatively, you can create the option for edit monitoring by adding a qualifier for RSS links. This allows the user to choose between default new pages RSS feeds and new edits RSS feeds (pmwiki.org has this option enabled).

   ## For new pages updates: http://example.com/wiki/HomePage?action=rss
   ## For edits updates: http://example.com/wiki/HomePage?action=rss&edits=1
   if(@$_REQUEST['edits'] && $action == 'rss')
     $FeedFmt['rss']['item']['guid'] = '{$PageUrl}?guid=$ItemISOTime';

WikiFarms

Also see: Cookbook:Farm Setup By Example, Cookbook:Wiki Farm Alternative

A WikiFarm is a collection of two or more wikis running on the same web server and sharing a set of common components. The term is based on the computing phrase "server farm".

This page provides some background information about WikiFarms and describes how to turn a "normal" configuration into a farm by adding a wiki. There are many ways to configure wiki farms; this page describes only one, in an effort to make it as simple as possible for the administrator who is creating a farm for the first time.

Why use a farm?

The primary motivation for using a wiki farm is to reduce the amount of administrative work involved in managing several wikis. In a farm, most of the PmWiki code is stored in one place and is shared by all the wikis. An administrator can (for example) upgrade to a new version of PmWiki on every wiki in the farm by simply updating the shared components in a single location.

From a reader's point of view, each wiki in a farm is completely independent, and appears as a separate web site. Each wiki in a farm:

  • has its own URL, and the URLs? can be in different domains
  • can have its own look and feel by using different skins
  • can have its own add-ons or "recipes" from the Cookbook
  • can have its own administrator responsible for local configuration

Why not to use a farm

Because the wikis in a farm are all independent, it is difficult (but not impossible) to provide services that require access to more than one wiki. For example, the PmWiki search function can only search within one wiki. Using a farm as a way of subdividing related content is generally a bad idea. A much better way to subdivide content is to use WikiGroups.

I still can't decide if I need a farm ...

The good news is that you don't have to decide in advance. In fact, the recommended procedure is to first do a "normal" or single installation of PmWiki. Use it for a while. Create pages and edit them. Get to know how to add recipes. Be sure to try out WikiGroups (they may be all you need).

Once you have decided that you need another wiki, you have two basic choices:

  1. Do a complete installation of PmWiki in a new directory. This gives you two totally independent wikis that are completely self-contained. This is not a wiki farm.
  2. Create a wiki farm using your existing wiki as the "home wiki" where most of the shared PmWiki components will live.

Choice number 1 can be a good choice for several reasons:

  • it is not a wiki farm, and requires no additional administrative knowledge - it's just two installations
  • if you decide to move one of the wikis to another server, you can simply copy the wiki directory structure to the second server, and it will work (assuming there is a web server and PHP in place).
  • you can run different versions of PmWiki on each wiki (good for testing new versions)
  • no matter how badly you mess up one installation, it doesn't affect the other

If you choose to create a wiki farm, then read on ...

Prerequisites

Before you create a farm, make sure that:

Creating the home wiki

You do have a working installation of PmWiki at this point, don't you? That's good, because your existing wiki is about to become the home wiki of your farm.

In the directory that contains your existing wiki, create the file local/farmconfig.php. This file is used to hold any local customizations that apply across the whole farm. For example, you could assign an admin password in farmconfig.php that will be used by all of the wikis in your farm.

If the URL used to access your existing wiki is http://www.example.com/pmwiki/ then a minimal farmconfig.php file would look like this:

<?php if (!defined('PmWiki')) exit();
$FarmPubDirUrl = 'http://www.example.com/pmwiki/pub';

This loads the variable $FarmPubDirUrl with the URL location of your home wiki's pub/ directory. All of the wikis in your farm share this pub/ directory. The pub/ directory holds skin definitions and GUI-edit buttons to be shared by all the wikis in the farm.

Amazing as it may sound, this completes all of the changes you need to make in order to turn your existing wiki into the home wiki of your farm.

Creating an additional wiki in your farm

1. Create a directory to hold the new wiki. This directory must be web-accessible, just like the directory that holds your home wiki.
2. Create a file called index.php in the directory with the following contents:
<?php include_once('path/to/pmwiki.php');
This allows your new wiki to share the PmWiki code stored in your home wiki. The path/to/pmwiki.php is the file path to pmwiki.php in your home wiki. Use an absolute file path (/home/username/pmwiki/pmwiki.php) or a relative file path (../pmwiki/pmwiki.php). Do not use a url path - there should not be an 'http://' in it anywhere. For a web server running under Windows, you need to use a complete file path as in C:/Apache Group/Apache2 /www/mynewwiki/.
3. Open a web browser and browse the URL of the new wiki. This will be a web address starting with 'http://'. PmWiki will attempt to automatically create a writable wiki.d/ directory where the wiki's pages will be stored. If you see an error message, follow the instructions. If you choose the option for a "slightly more secure installation" be sure to execute both commands.

Your new wiki is now set up, and your farm now contains 2 wikis. To add more wikis, just repeat these 3 steps.

Customization

Each wiki in a farm inherits the settings stored in farmconfig.php. Do any customization that you want to apply farm-wide (to all the wikis) in farmconfig.php.

Create a local/ directory within each wiki's directory to hold local customizations that apply only to that wiki. You should at least create the local/config.php file with a new title, like so :

<?php if (!defined('PmWiki')) exit();
  ## Title of your farmed wiki
  $WikiTitle = 'New Wiki';

Farm-wide customizations are processed before the individual wiki local customizations.

The PmWiki variable $FarmD points to the directory in which pmwiki.php is installed, and your home wiki, and it is used as a prefix to allow the other wikis to share PmWiki components. For example:

  • $FarmD/scripts/ points to the shared scripts/ directory
  • $FarmD/pub/ points to the shared pub/ directory
  • $FarmD/cookbook/ points to the shared cookbook/ directory

Any scripts you include in farmconfig.php must be included with a line such as:

include_once("$FarmD/cookbook/scriptfile.php");
Note the double quotes - single quotes may work for per farm inclusions, but they will not work for $FarmD.

Notes

  • The terminology used to describe wiki farms is not used consistently. See WikiFarmTerminology for more info.
  • It is important to remember that not all of the recipes in the Cookbook have been written for or tested with farms. Be sure to look for instructions on how to use a recipe on a farm.
  • There are many, many more things you can do with farms. Some are described on PmWiki:WikiFarmsAdvanced which also contains links to step-by-step examples of setting up a farm.

Password use/authorization on farm wikis:

How come when I switch to another wiki within a farm, I keep my same authorization?

PmWiki uses PHP sessions to keep track of authentication/authorization information, and by default PHP sets things up such that all interactions with the same server are considered part of the same session.

An easy way to fix this is to make sure each wiki is using a different cookie name for its session identifier. Near the top of one of the wiki's local/config.php files, before calling authuser or any other recipes, add a line like:

session_name('XYZSESSID');

You can pick any alphanumeric name for XYZSESSID; for example, for the cs559-1 wiki you might choose

session_name('CS559SESSID?');

This will keep the two wikis' sessions independent of each other.

Categories: WikiFarms


FAQ

This page will attempt to summarize some of the more commonly asked questions. The answers are on the corresponding pages (see link). If you have a question which isn't answered here, you can leave your question on the Questions page or search for documentation using the search facility. More documentation can be found on the documentation index page.


Troubleshooting

Pmwiki is pretty robust and can automatically adapt to a very wide variety of environments. However, sometimes things don't go as we expect, so we're cataloging common errors and their fixes here.

Troubleshooting Frequently Asked Questions

Note: This page on pmwiki.org is probably not the best place to post questions. Consider seeking assistance from the pmwiki-users mailing list, or post your question on the PmWiki:Questions page.

Why am I seeing strange errors after upgrading?

Make sure all of the files were updated, in particular pmwiki.php.

This question sometimes arises when an administrator hasn't followed the advice, which used to be less prominent, on the installation and initial setup tasks pages and has renamed pmwiki.php instead of creating an index.php wrapper script. If you have renamed pmwiki.php to index.php, then the upgrade procedure won't have updated your index.php file. Delete the old version and create a wrapper script so it won't happen again.

Sometimes an FTP or other copy program will fail to transfer all of the files properly. One way to check for this is by comparing file sizes.

Be sure all of the files in the wikilib.d/ directory were also upgraded. Sometimes it's a good idea to simply delete the wikilib.d/ directory before upgrading. (Local copies of pages are stored in wiki.d/ and not wikilib.d/.)

Make sure that the file permissions are correct. The official files have a restricted set of permissions that might not match your site's needs.

If you use a custom pattern for $GroupPattern make sure that it includes Site ($SiteGroup) and since PMWiki 2.2 also SiteAdmin? ($SiteAdminGroup). Otherwise migration may fail (e.g. missing SiteAdmin? for PMWiki 2.2 and later) and/or login does not work.
Additionally Main ($DefaultGroup) should be included too.

I'm suddenly getting messages like "Warning: fopen(wiki.d/.flock): failed to open stream: Permission denied..." and "Cannot acquire lockfile"... what's wrong?

Something (or someone) has changed the permissions on the wiki.d/.flock file or the wiki.d/ directory such that the webserver is no longer able to write the lockfile. The normal solution is to simply delete the .flock file from the wiki.d/ directory -- PmWiki will then create a new one. Also be sure to check the permissions on the wiki.d/ directory itself. (One can easily check and modify permissions of the wiki.d/ directory in FileZilla (open-source FTP app) by right-clicking on the file > File attributes)

My links in the sidebar seem to be pointing to non-existent pages, even though I know I created the pages. Where are the pages?

Links in the sidebar normally need to be qualified by a WikiGroup in order to work properly (use [[Group.Page]] instead of [[Page]]).
Also: Make sure you type SideBar with a capital B.

Why am I seeing "Warning: Cannot modify header information - headers already sent ..." messages at the top of my page.

If this is the first or only error message you're seeing, it's usually an indication that there are blank lines or spaces before the <?php or after the ?> in a local customization file. Double-check the file and make sure there aren't any blank lines or spaces before the initial <?php. It's often easiest and safest to eliminate any closing ?> altogether. On Windows, it may be necessary to use a hex editor to convert LFCR line endings to LF line endings in the local\config.php file.

If the warning is appearing after some other warning or error message, then resolve the other error and this warning may go away.

How do I make a PHP Warning about function.session-write-close go away?

If you are seeing an error similar to this

Warning: session_write_close() [function.session-write-close]:
open(/some/filesystem/path/to/a/directory/sess_[...]) failed: No such file
or directory (2) in /your/filesystem/path/to/pmwiki.php on line NNN

PmWiki sometimes does session-tracking using PHP's session-handling functions. For session-tracking to work, some information needs to be written in a directory on the server. That directory needs to exist and be writable by the webserver software. For this example, the webserver software is configured to write sessions in this directory

/some/filesystem/path/to/a/directory/

but the directory doesn't exist. The solution is to do at least one of these:

  • Create the directory and make sure it's writable by the webserver software
  • Provide a session_save_path value that points to a directory that is writable by the server, e.g. in config.php:
session_save_path('/home/someuser/tmp/sessions'); # unix-type OS
session_save_path('C:/server/tmp/sessions'); # Windows

Why is PmWiki prompting me multiple times for a password I've already entered?

This could happen like out of nowhere if your hosting provider upgrades to PHP version 5.3, and you run an older PmWiki release. Recent PmWiki releases fix this problem.

Alternatively, this may be an indication that the browser isn't accepting cookies, or that PHP's session handling functions on the server aren't properly configured. If the browser is accepting cookies, then try setting $EnableDiag=1; in local/config.php, run PmWiki using ?action=phpinfo, and verify that sessions are enabled and that the session.save_path has a reasonable value. Note that several versions of PHP under Windows require that a session_save_path be explicitly set (this can be done in the local/config.php file). You might also try setting session.auto_start to 1 in your php.ini.

See also the question I have to log in twice below.

I edited config.php, but when I look at my wiki pages, all I see is "Parse error: parse error, unexpected T_VARIABLE in somefile on line number."

You've made a mistake in writing the PHP that goes into the config.php file. The most common mistake that causes the T_VARIABLE error is forgetting the semi-colon (;) at the end of a line that you added. The line number and file named are where you should look for the mistake.

Searches and pagelists stopped working after I upgraded -- no errors are reported, but links to other pages do not appear (or do not appear as they should) -- what gives?

Be sure all of the files in the wikilib.d/ directory were also upgraded. In particular, it sounds as if the Site.PageListTemplates page is either missing (if no links are displayed) or is an old version (if the links do not appear as they should). Also make sure that read-permissions (attr) are set for the pages Site.PageListTemplates and Site.Search.

Some of my posts are coming back with "403 Forbidden" errors, "Not Acceptable", or "Internal Server Error". This happens with some posts but not others.

Your webserver probably has mod_security enabled. The mod_security "feature" scans all incoming posts for forbidden words or phrases that might indicate someone is trying to hack the system, and if any of them are present then Apache returns the 403 Forbidden error. Common phrases that tend to trigger mod_security include "curl ", "wget", "file(", and "system(", although there are many others.

Since mod_security intercepts the requests and sends the "forbidden" message before PmWiki ever gets a chance to run, it's not a bug in PmWiki, and there's little that PmWiki can do about it. Instead, one has to alter the webserver configuration to disable mod_security or reconfigure it to allow whatever word it is forbidding. Some sites may be able to disable mod_security by placing SecFilterEngine off in a .htaccess file.

I get the following message when attempting to upload an image, what do I do?

Warning: move_uploaded_file(): SAFE MODE Restriction in effect. The script whose uid is 1929 is not allowed to access /home/onscolre/public_html/pmwikiuploads/Photos owned by uid 33 in /home/onscolre/public_html/pmwiki/scripts/upload.php on line 198

PmWiki can't process your request

?cannot move uploaded file to /home/onscolre/public_html/pmwikiuploads/FoundationPupilsIn1958?.jpeg

We are sorry for any inconvenience.

Your server is configured with PHP Safe Mode enabled. Configure your wiki to use a site-wide uploads prefix, then create the uploads/ directory manually and set 777 permissions on it (rather than letting PmWiki create the directory).

I'm starting to see "Division by zero error in pmwiki.php..." on my site. What's wrong?

It's a bug in PmWiki that occurs only with the tables markup and only for versions of PHP >= 4.4.6 or >= 5.2.0. Often it seems to occur "out of nowhere" because the server administrator has upgraded PHP. Try upgrading to a later version of PmWiki to remove the error, or try setting the following in local/config.php:

    $TableRowIndexMax = 1;

I have to log in twice (two times) (2 times). -or- My password is not being required even though it should. -or- I changed the password but the old password is still active. -or- My config.php password is not over-riding my farmconfig.php password.

It could happen if (farm)config.php, or an included recipe, directly calls the functions CondAuth(), or RetrieveAuthPage?(), PageTextVar?(), PageVar?() and possibly others, before defining all passwords and before including AuthUser (if required).

The order of config.php is very significant.


AvailableActions

Page actions are applied to wiki pages, as a query string appended to the URL. Security can be applied to all default actions, and script actions with one exception, but not diag actions, through the use of passwords.

Also documented are all other URL queries.

PmWiki Actions

See also site page actions.

?action=attr
displays dialog for setting/changing password of the specified page or group of pages, see passwords, see also $EnablePostAttrClearSession if you do not want to have the session cleared after validating change General use of passwords and login

?action=browse
display the specified page (default action if no ?action= is present)

?action=crypt
displays a form for generating hashed passwords out of clear text for usage in your config.php

?action=diff
show a change history of the specified page, see page history History of previous edits to a page

?action=download&upname=file.ext
retrieve the page's attachment named file.ext, see $EnableDirectDownload

?action=edit
edit the specified page, see basic editing PmWiki's basic edit syntax

?action=login
prompt visitor for username/password, by default using Site.AuthForm

?action=logout
remove author, password, and login information

?action=print
display the specified page using the skin specified by $ActionSkin['print']

?action=refcount
bring up the reference count form, which allows the user to generate a list of links (all, missing, existing or orphaned) in or from specified groups. See Ref Count Link references counts on pages . Part of the core distribution but must be enabled by the administrator.

?action=search
displays searchbox on current page, see search Targeting and customizing search results
?action=search&q=searchterm
performs search with searchterm and displays results on current page
?action=search&q=link=pagename
performs backlinks search with ''pagename' and displays results on current page

?action=source
show page source

?action=atom
?action=rdf
?action=rss
?action=dc
If web feeds are enabled, returns a syndication feed based on the contents of the page or other options provided by the url, see web feeds Web feed notification of changes

?action=upload
display a form to upload an attachment for the current group, see uploads Uploading and linking to attachments


Query string parameters

?from=page name
use when a page is redirected

?n=page name
display page

?setprefs=SomeGroup.CustomPreferences?
sets cookie to custom preferences page. See site preferences Customisable browser setting preferences: Access keys, edit form

Actions enabled by $EnableDiag

The following actions are available only if you set $EnableDiag = 1; in your configuration file. They can be used for debugging and should not be set in a production environment.

?action=ruleset
displays a list of all markups in 3 columns:
  • column 1 = markup-name (1. parameter of markup() )
  • column 2 = when will rule apply (2. parameter of markup() )
  • column 3 = PmWiki's internal sort key (derived from #2)
(see Custom Markup Using the Markup() function for custom wiki syntax; migration to PHP 5.5 ).
To see more than what ?action=ruleset gives you, apply the Cookbook:MarkupRulesetDebugging recipe: it can also show the pattern and the replacement strings.
  • doesn't make use of PmWiki's authorization mechanisms.

?action=phpinfo
displays the output of phpinfo() and exits. no page will be processed
  • doesn't make use of PmWiki's authorization mechanisms.

?action=diag
displays a dump of all global vars and exits. no page will be processed
  • doesn't make use of PmWiki's authorization mechanisms.


Actions enabled by PmWiki Scripts

?action=analyze
see Site Analyzer and Analyze Results

?action=approvesites
see Url approvals Require approval of Url links
  • doesn't make use of PmWiki's authorization mechanisms.


Actions enabled by recipes

(more information about Custom Actions)

?action=admin
see Cookbook:UserAuth2 A user-based permission granting and authentication module
?action=backup
see Cookbook:BackupPages Automatically back up the wiki.d directory to a .zip file
?action=clearsky
see Cookbook:SearchCloud Creates a list of search terms used on a PmWiki site.
?action=comment
see Cookbook:CommentBox Adds a simple form to post comments
?action=comments
see Cookbook:Comments Comment addon - comments in separate files
?action=comment-rss
see Cookbook:CommentDb Comment recipe - with pagination and RSS feed
?action=convert
see Cookbook:ROEPatterns Replace On Edit
?action=converttable
Cookbook:ConvertTable Convert table action
?action=copy
see Cookbook:MovePage Move and copy wiki pages
?action=csv
see CSVAction Adds a ?action=csv capability to pmwiki to output tables as a CSV
?action=downloaddeleted
?action=delattach
?action=delattach
?action=deldelattach
?action=fileinfo
?action=thumbnail
?action=undelattach
Cookbook:Attachtable Actions to rename, delete & restore deleted attachments, as well as an attachlist replacement to use those actions, show file types and list attachment references.
?action=delete
see Cookbook:DeleteAction
?action=discuss
see Cookbook:DiscussionTab Provide a skin with a "discussion" tab and "article" tab, etc.
?action=downloadman
see Cookbook:DownloadManager How can I know how many times a file was downloaded from my wiki?
?action=expirediff
see Cookbook:ExpireDiff How to remove a page's history
?action=import
see Cookbook:ImportText Import text files as PmWiki pages
?action=move
see Cookbook:MovePage Move and copy wiki pages
?action=PageUrl?
see Cookbook:CommentBoxPlus Simple styled form to post comments, plus comment counter
?action=pageindex
see Cookbook:ListCategories use categories as tags
?action=pdf
see Cookbook:GeneratePDF Generate PDF versions of pages (?action=pdf) or Cookbook:PmWiki2PDF Generate a PDF; back up all wiki pages in PDF format
?action=postupload2
see Cookbook:UploadForm Alternative file upload form using (:input file:)
?action=publish
see Cookbook:PublishPDF Typesets wiki page collections into PDF (finalist: New Zealand open source awards 2008)
?action=purgeqns
see Cookbook:ASCIIMath Display MathML? rendered ascii formula into PmWiki 2.x pages
?action=pwchange
see Cookbook:UserAuth2 A user-based permission granting and authentication module
?action=imgtpl
(the imgtpl action is called automatically and should not be called by a link in a wiki page)
?action=createthumb
(the createthumb action is called automatically and should not be called by a link in a wiki page)
?action=mini
(this action is called automatically and should not be called by a link in a wiki page)
?action=purgethumbs
see Cookbook:ThumbList A thumbnail picture gallery for PmWiki
see Cookbook:Mini Simple, lightweight, un-bloated gallery with thumbnail generator
?action=recipecheck
see Cookbook:RecipeCheck Check for new versions of recipes on pmwiki.org
?action=regen
see Cookbook:PageRegenerate Make PmWiki regenerate a page, as if someone had done an edit+save sequence.
?action=rename
?action=links
see Cookbook:RenamePage Rename a wiki page from a browser
?action=share
?action=unshare
see Cookbook:SharedPages Share selected pages among several wikis on a common server, as in WikiFarms
?action=sitemapaddgroups
?action=sitemapupdate
see Cookbook:Sitemapper Adds a dynamically generated sitemap to PmWiki.
?action=totalcounter
see Cookbook:TotalCounter A statistic counter - counts page views, users, languages, browsers, operating systems, referers, locations and web bots
?action=trash
?action=untrash
see Cookbook:Trash "safely delete" pages so that they can be restored and listed with pagelists
?action=webadmin
see Cookbook:WebAdmin PHP file manager, works without ftp client
?action=zap
see Cookbook:ZAP The ZAP forms processor handles data and file management, page insertions (forums, blogs), email & newsletters, e-commerce, and more.


Query string parameters enabled by recipes

?color=colorscheme

:?setcolor=colorscheme

?skintheme=theme
?setskintheme=theme
see Cookbook:ChoiceColorChanger {ChoiceColorChanger $:Summary}
?skin=skinname
?setskin=skinname
see SkinChange change skin via query or cookie setting

Custom actions


AuthUser

AuthUser is PmWiki's identity-based authorization system that allows access to pages to be controlled through the use of usernames and passwords. AuthUser can be used in addition to the password-based scheme that is PmWiki's default configuration.

AuthUser is a very flexible system for managing access control on pages, but flexibility can also bring complexity and increased maintenance overhead to the wiki administrator. This is why PmWiki defaults to the simpler password-based system. For some thoughts about the relative merits of the two approaches, see PmWiki:ThoughtsOnAccessControl.

See also: Cookbook:Quick Start for AuthUser.

Activating AuthUser

To activate PmWiki's identity-based system, add the following line to local/config.php:

    include_once("$FarmD/scripts/authuser.php");

Ensure that you have set a site wide admin password, otherwise you will not be able to edit SiteAdmin.AuthUser.

Note: Older versions of PmWiki (before 2.2.0-beta58) use Site.AuthUser.

PmWiki caches some group and page authorization levels when a page is accessed. For this reason, it is better to include authuser.php quite early in config.php, notably

(If you don't use a custom PageStore? class and i18n, include authuser.php first thing in config.php.)

All other recipes should be included after these.

Creating user accounts

Most of AuthUser's configuration is performed via the SiteAdmin.AuthUser page. To change the AuthUser configuration, simply edit this page like any other wiki page (you'll typically need to use the site's admin password for this).

To create a login account, simply add lines to SiteAdmin.AuthUser that look like:

    username: (:encrypt password:)

For example, to create a login account for "alice" with a password of "wonderland", enter:

    alice: (:encrypt wonderland:)

When the page is saved, the "(:encrypt wonderland:)" part of the text will be replaced by an encrypted form of the password "wonderland". This encryption is done so that someone looking at the SiteAdmin.AuthUser page cannot easily determine the passwords stored in the page.

To change or reset an account's password, simply replace the encrypted string with another (:encrypt:) directive.

The password cannot contain spaces, tabs, new lines, columns ":" and equals "="; on some systems it should contain at least 4 characters. Usernames and passwords are case sensitive, eg. "User" is not the same as "user".

Controlling access to pages by login

Pages and groups can be protected based on login account by using "passwords" of the form id:username in the password fields of ?action=attr (see PmWiki.Passwords). For example, to restrict a page to being edited by Alice, one would set the password to "id:alice".

It's possible to use multiple "id:" declarations and passwords in the ?action=attr form, thus the following setting would allow access to Alice, Carol, and anyone who knows the password "quick":

    quick id:alice,carol

To allow access to anyone who has successfully logged in, use "id:*".

One can also perform site-wide restrictions based on identity in the $DefaultPasswords array: e.g.

    # require valid login before viewing pages
    $DefaultPasswords['read'] = 'id:*';
    # Alice and carol may edit
    $DefaultPasswords['edit'] = 'id:alice,carol';
    # All admins and Fred may edit
    $DefaultPasswords['edit'] = array('@admins', 'id:Fred');

You can change the $DefaultPasswords array in local customization files such as:

  • local/config.php (for entire wiki)
  • farmconfig.php (for entire wikifarm)

Organizing accounts into groups

AuthUser also makes it possible to group login accounts together into authorization groups, indicated by a leading "@" sign. As with login accounts, group memberships are maintained by editing the SiteAdmin.AuthUser page. Group memberships can be specified by either listing the groups for a login account (person belongs to groups) or the login accounts for a group (group includes people). You can repeat or mix-and-match the two kinds as desired:

    @writers: alice, bob
    carol: @writers, @editors
    @admins: alice, dave

Then, to restrict page access to a particular group, simply use "@group" as the "password" in ?action=attr or the $DefaultPasswords array, similar to the way that "id:username" is used to restrict access to specific login accounts.

Excluding individuals from password groups

Group password memberships are maintained by editing the SiteAdmin.AuthUser page. To specify a password group that allows access to anyone who is authenticated, you can specify:

    @wholeoffice: *

If you need to keep "Fred" out of this password group :

    @wholeoffice: *,-Fred

To allow all users except Fred to change page attributes, for example, you can add to config.php :

    $DefaultPasswords['attr'] = array('id:*,-Fred');

Getting account names and passwords from external sources

The AuthUser script has the capability of obtaining username/password pairs from places other than the SiteAdmin.AuthUser page, such as passwd-formatted files (usually called '.htpasswd' on Apache servers), LDAP servers, or even the local/config.php file.

Passwd-formatted files (.htpasswd/.htgroup)

Passwd-formatted files, commonly called .htpasswd files in Apache, are text files where each line contains a username and an encrypted password separated by a colon. A typical .htpasswd file might look like:

    alice:vK99sgDV1an6I
    carol:Q1kSeNcTfwqjs?

To get AuthUser to obtain usernames and passwords from a .htaccess file, add the following line to SiteAdmin.AuthUser, replacing "/path/to/.htpasswd" with the filesystem path of the .htpasswd file:

    htpasswd: /path/to/.htpasswd

Creation and maintenance of the .htpasswd file can be performed using a text editor, or any number of other third-party tools available for maintaining .htpasswd files. The Apache web server typically includes an htpasswd command for creating accounts in .htpasswd:

    $ htpasswd /path/to/.htpasswd alice
    New password:
    Re-type new password:
    Adding password for user alice
    $

Similarly, one can use .htgroup formatted files to specify group memberships. Each line has the name of a group (without the "@"), followed by a colon, followed by a space separated list of usernames in the group.

    writers: carol
    editors: alice carol bob
    admins: alice dave

Note that the groups are still "@writers", "@editors", and "@admins" in PmWiki even though the file doesn't specify the @ signs. To get AuthUser to load these groups, use a line in SiteAdmin.AuthUser like:

    htgroup: /path/to/.htgroup

Configuration via local/config.php

AuthUser configuration settings can also be made from the local/config.php file in addition to the SiteAdmin.AuthUser page. Such settings are placed in the $AuthUser array, and must be set prior to including the authuser.php script. Some examples:

    # set a password for alice
    $AuthUser['alice'] = crypt('wonderland');
    # set a password for carol
    $AuthUser['carol'] = '$1$CknC8zAs$dC8z2vu3UvnIXMfOcGDON0';
    # define the @editors group
    $AuthUser['@editors'] = array('alice', 'carol', 'bob');
    # Use local/.htpasswd for usernames/passwords
    $AuthUser['htpasswd'] = 'local/.htpasswd';
    # Use local/.htgroup for group memberships
    $AuthUser['htgroup'] = 'local/.htgroup';

Configuration via LDAP

Authentication can be performed via an external LDAP server -- simply set an entry for "ldap" in either SiteAdmin.AuthUser or the local/config.php file.

    # use ldap.airius.com for authentication
    $AuthUser['ldap'] = 'ldap://ldap.airius.com/ou=People,o=Airius?cn?sub';

Make sure to include AuthUser below the entry for the ldap server:

    # Want to use AuthUser so we can use ldap for passwords
    include_once("$FarmD/scripts/authuser.php");

And remember to assign the Security Variables for edit and history (or whatever):

    #Security Variables set login for edit & history page
    # to let anyone edit that has an ldap entry:
    $HandleAuth['diff'] = 'edit';
    $DefaultPasswords['edit'] = 'id:*';
    $Author = $AuthId;

LDAP authentication in AuthUser closely follows the model used by Apache 2.0's mod_auth_ldap module; see especially the documentation for AuthLDAPUrl for a description of the url format.

For servers that don't allow anonymous binds, AuthUser provides $AuthLDAPBindDN and $AuthLDAPBindPassword variables to specify the binding to be used for searching.

See also Cookbook:AuthUser via Microsoft LDAP

Setting the Author Name

By default, PmWiki will use a login name in the Author field of the edit form, but allows the author to change this value prior to saving. To force the login name to always be used as the author name, use the following sequence in config.php to activate AuthUser:

    include_once("$FarmD/scripts/authuser.php");
    $Author = $AuthId; # after include_once()

To allow more flexibility, but still enable changes to be linked to the authorized user, one can give the author name a prefix of the $AuthId instead:

    include_once("$FarmD/scripts/author.php");
    include_once("$FarmD/scripts/authuser.php");
    if ($Author) {
	if (strstr($Author, '-') != false) {
	    $Author = "$AuthId-" . preg_replace('/^[^-]*-/', '', $Author);
	} else if ($Author != $AuthId) {
	    $Author = $AuthId . '-' . $Author;
	} else {
	    $Author = $AuthId;
	}
    } else {
	$Author = $AuthId;
    }
    $AuthorLink = "[[~$Author]]";

The above will allow the user to put in the author name of their choice, but that will always be replaced by that name prefixed with "$AuthId-". The reason why $AuthorLink needs to be set is that, if it isn't, the RecentChanges page will have the wrong link in it.

Removing the "Author" edit field

To force users to edit with their AuthID? instead of having a field they can place any name in. This enables administration to keep track of who is doing what better. This line also links the Author name to their Profile.
Go to Site.EditForm, remove the line
$[Author]: (:input e_author:)
or replace it with
$[Author]: [[Profiles/{$Author}]]

Authorization, Sessions, and WikiFarms

PmWiki uses PHP sessions to keep track of any user authorization information. By default PHP is configured so that all interactions with the same server (as identified by the server's domain name) are treated as part of the same session.

What this means for PmWiki is that if there are multiple wikis running within the same domain name, PHP will treat a login to one wiki as being valid for all wikis in the same domain. The easiest fix is to tell each wiki to have use a different "session cookie". Near the top of a wiki's local/config.php file, before calling authuser or other recipes, add a line like:

session_name('XYZSESSID');

The XYZSESSID can be any unique name (letters only is safest).

See Also

Can I specify authorization group memberships from with local/config.php?

Yes -- put the group definition into the $AuthUser array (in config.php):

        $AuthUser['@editors'] = array('alice', 'carol', 'bob');

Can I have multiple admin groups?

Yes, define the groups with array('@admins', '@moderators'); like this:

  $DefaultPasswords['admin'] = array( crypt('masterpass'), # global password
    '@admins', '@moderators', # +users in these groups
    'id:Fred', 'id:Barney');  # +users Fred and Barney

I'm running multiple wikis under the same domain name, and logins from one wiki are appearing on other wikis. Shouldn't they be independent?

This is caused by the way that PHP treats sessions. See PmWiki.AuthUser#sessions for more details.

Is there any way to record the time of the last login for each user when using AuthUser? I need a way to look for stale accounts.

See Cookbook:UserLastAction.

Though every setting seems correct, authentication against LDAP is not working. There is nothing in ldap log, what's wrong?

Be sure ldap php module is installed ( on debian apt-get install php(4|5)-ldap ; apache(2)ctl graceful )

The login form asks for username and password, but only password matters.

Username can be left blank and it still signs in under the account. Is this intentional and if so, can I change it so that the username and password must both be entered? - X 1/18/07 Never mind I think this has something to do with using the admin password. I created a test account and it's working ok.

Make sure you are not entering the admin password when testing the account because, if the password is equal to the admin password, it will authenticate directly through the config.php file and skip any other system.

Do note that even with AuthUser activated you can still log in with a blank username and only entering the password. In that case any password you enter will be "accepted" but only passwords which authenticate in the given context will actually give you any authorization rights. Using this capability AuthUser comfortably coexists with the default password-based system.

If you want to require both username and password, then you need to set an admin id before including authuser.php:

## Define usernames and passwords.
$AuthUser['carol'] = '$1$CknC8zAs$dC8z2vu3UvnIXMfOcGDON0';

## Enable authentication based on username.
include_once('scripts/authuser.php');

# $DefaultPasswords['admin'] = crypt('secret');
$DefaultPasswords['admin'] = 'id:carol';

A username and password will then be required before login is successful.

Is there any way to hide IP addresses once someone has logged in so that registered users can keep their IP addresses invisible to everyone except administrators? - X 1/18/07

Yes, see solution provided at PITS:00400.

Is there a way that people could self-register through AuthUser?

You can see HtpasswdForm and AuthUserSignup for two recipes providing this feature.

I would like it that after I have AuthUser turned and a user is authenticated to get on my site, that if I have a password put on a particular page or group that they don't get the AuthUser form to show up (username and password), but only the typical field for password?

See this thread of the mailing list.


Blocklist

The block list is one of a number of security measures that can be taken to protect your wiki from spam and other unwelcome postings.

Unfortunately, the open-editability of many wiki systems often makes them attractive targets for "link spam" or "wikispam", in which links are added to pages in an effort to increase search engine rankings or drive traffic to other sites. Also, many link spammers have developed automated systems to locate sites that accept visitor input and attempt to flood the site with unwanted links. Also, and harder to deal with, is just plain wiki vandalism where nonsense changes are made, often replacing entire pages.

By far the best countermeasure against wikispam is to restrict editing through the use of passwords (see Passwords and Passwords Admin). Experience has shown that passwords can be effective even if the password is widely known, and even if the password is publicly available on the site itself. However, there are many cases where passwording may be an impediment, so these will generally want to use some form of blocklist.

Blocklist basics

A blocklist is a list of IP addresses, phrases, and expressions which are prevented from being added into pages on the website. PmWiki is distributed with a built-in blocklisting capability; blocklists can be enabled by adding the following line to local/config.php:

$EnableBlocklist = 1;

This tells PmWiki to scan the SiteAdmin.Blocklist page and the "SiteAdmin?.Blocklist-Farm" page (and possibly other pages -- see below) looking for phrases and IP addresses to be excluded from posting to the site.

Blocking by word or phrase

The simplest form of block is simply a line containing "block:" followed by a word or phrase to be excluded from postings. For example, a line like

block:spam.com

in SiteAdmin?.Blocklist will block any posts containing the string "spam.com" (case-insensitive) anywhere in the post.

Blocking by IP address

Sometimes we wish to restrict posts coming from particular addresses or address ranges that are known as sources of wikispam. If a blocklist page contains IP addresses of the form "a.b.c.d" or "a.b.c.*", then any posts coming from that address or range will be blocked.

To find an author's IP address, try hovering the mouse over the author name in the page history for a page.

Blocking by regular expression or pattern

Blocking on simple words can sometimes pose difficulties; for example, a simple "block:cial" entry will also block the word "specialist". For these cases it's often helpful to use a regular expression, as in:

block:/\bcial\b/

This says to block "cial" only if it doesn't occur in the middle of a larger word. The leading slash (/) after "block:" tells PmWiki to use a regular expression match instead of a simple string match. (Blocklist uses PCRE or "Perl Compatible Regular Expressions"; see http://php.net/manual/en/ref.pcre.php for more information.)

Regular expression to block 'href'

If you want to block 'href', you can use the following markup:

block:/[^\w\\]href\b/

which blocks 'href', but neither '\href' nor 'toughref'.

The regular expression can be interpreted as follows: Match any character that is neither a word character nor a '\', followed by href which ends in a word boundary.

Letting authors know why they've been blocked

By default, blocklist only tells an author that a particular edit has been blocked, but doesn't give a specific reason for the blocking (e.g., the offending phrase). Setting the following in a local customization file will also provide the reasons for the block:

$EnableWhyBlocked = 1;

Managing multiple blocklists

PmWiki allows blocklist entries to come from multiple pages by setting the $BlocklistPages variable. By default $BlocklistPages is set to "SiteAdmin?.Blocklist", as well as any automatically downloaded blocklists as described below. PmWiki will use all entries in all the blocklists for filtering wikispam. Setting a value of $BlocklistPages changes the default:

$BlocklistPages = array('Main.Blocklist', 'Test.Blocklist');

The order of blocklists really doesn't matter -- all of the blocklist pages ultimately get used, and the unblock: entries are processed after all of the blocklist pages have been loaded.

Automatically downloaded blocklists

Maintaining blocklists is relatively easy to do, but can become tedious over time. Several groups have formed and maintain "shared blocklists", where a common blocklist is made available to all. PmWiki's blocklist capability has built-in features for automatically downloading and updating such shared blocklists.

If you're just in a hurry to make use of some standard blocklists, make the following setting in local/config.php:

$EnableBlocklist = 10;

This tells PmWiki to not only enable blocklists on the site, but to also configure itself to automatically retrieve and maintain local copies of well-known blocklists such as chongqed.org and MoinMaster. These local copies will be saved in SiteAdmin?.Blocklist-Chongqed and SiteAdmin?.Blocklist-MoinMaster? and refreshed once per day (as determined by the value of $BlocklistDownloadRefresh).

To automatically retrieve the SiteAdmin.Blocklist page used at pmwiki.org, add the following setting in local/config.php:

$BlocklistDownload["$SiteAdminGroup.Blocklist-PmWiki"] = array('format' => 'pmwiki');

Ignoring specific entries in a blocklist (unblock)

When using a large master blocklist or blocklists automatically refreshed from external sites, it may be that some entries in the blocklists are inappropriate or overeager and block legitimate content. In this case a wikiadministrator can use "unblock" in a blocklist page to ignore an entry from the blocklist. For example, to allow "spam.com" even if another blocklist has a block entry for it:

unblock:spam.com

In order for unblocking to work the phrase or pattern following "unblock:" must be exactly the same as the original.

Permissions on blocklist pages

In general, an administrator will want to edit-protect the SiteAdmin?.Blocklist and any other blocklist pages to prevent arbitrary changes to the blocklist (see Passwords). Since most pages in the SiteAdmin?.* group are edit-protected by default anyway, this usually isn't a problem.

Administrators may also wish to read-protect the various blocklist pages so that others do not know the exact phrases and/or IP addresses that are being blocked. (By their nature blocklists tend to contain phrases or terms that may be offensive or inappropriate to some.)

Any pages created via automatic download (see above) are automatically locked against viewing except by administrators.

administrators (intermediate)

Detailed configuration of automatically downloaded blocklists

Automatic downloading of blocklist information is controlled by the $BlocklistDownload array. An entry for MoinMaster? might look like:

$BlocklistDownload["$SiteAdminGroup.Blocklist-MoinMaster?"] = array(
'format' => 'regex',
'refresh' => 86400);

This says to download the blocklist data from the given url into the SiteAdmin?.Blocklist-MoinMaster? page, that the entries in the blocklist are regular expressions, and to refresh the information every 86,400 seconds (one day).

If 'refresh' is omitted, then the page will be refreshed at the time interval given by $BlocklistDownloadRefresh (default one day). If 'format' is omitted, the page is assumed to have PmWiki-formatted entries as described above. If 'url' is omitted, then the blocklist information is downloaded from a standard location on the pmwiki.org site.

To force a refresh of an automatically downloaded blocklist, simply delete the existing page -- a new version will be installed upon the next blocklist scan. Blocklist pages are checked for download in response to any ?action=edit request.

If you are specifying your Blocklist-Pages in the config.php you have to specify the automatically updated pages too, else they won't be updated or created even if you use $EnableBlocklist = 10; .

Farm-wide blocklist

A blocklist can be applied farm-wide (see SharedPages). After these pages are created they can be moved into the farm shared.d/ directory:

Blocklist Variables

The following variables help control the configuration and operation of blocklists:

%apply=item id=EnableBlocklist?%$EnableBlocklist
If set to a non-zero value, then blocklists are enabled on the site. If set to a value of ten or higher, then add entries for automatic downloads of standard blocklists.
$EnableBlocklist = 1; # enable blocklists
$EnableBlocklist = 10; # auto-configure standard blocklists
%apply=item id=EnableWhyBlocked?%$EnableWhyBlocked
By default, authors are not told which particular phrases or IP addresses are causing a particular post to be blocked; setting $EnableWhyBlocked to 1 provides this information.
$EnableWhyBlocked = 1; # give reasons for blocking
%apply=item id=BlocklistPages?%$BlocklistPages
An array of pages to be checked for blocklist entries. The elements of the array may contain page variables. Defaults to "Site.Blocklist", plus any other automatically downloaded blocklist pages.
%apply=item id=BlocklistMessageFmt?%$BlocklistMessageFmt
The message to provide the author whenever a post has been blocked.
%apply=item id=BlockedMessagesFmt?%$BlockedMessagesFmt
If $EnableWhyBlocked is set, defines the text to use for each type of block being performed. Currently only 'ip' and 'text' are recognized.
BlockedMessagesFmt?['ip'] = "IP address blocked from posting: ";
$BlockedMessagesFmt['text'] = "Text blocked from posting: ";
%apply=item id=BlocklistDownload?%$BlocklistDownload
An array of automatically-downloaded blocklists. The keys of the array are the pages in which the blocklists should be stored, the values contain the url, format, and refresh interval for the downloaded blocklist.
  # Download the MoinMaster blocklist every twelve hours
  $BlocklistDownload["$SiteAdminGroup.Blocklist-MoinMaster"] = array(
    'url' => 'http://moinmaster.wikiwikiweb.de/BadContent?action=raw',
    'format' => 'regex',
    'refresh' => 43200);
  # Download a shared blocklist from pmwiki.org every day
  $BlocklistDownload["$SiteAdminGroup.Blocklist-Shared"] = array(
    'format' => 'pmwiki');
%apply=item id=BlocklistDownloadRefresh?%$BlocklistDownloadRefresh
The default refresh interval for any $BlocklistDownload entries that don't explicitly specify a 'refresh' value.
# perform automatic downloads once per week by default
$BlocklistDownloadRefresh = 86400 * 7;
%apply=item id=BlocklistDownloadFmt?%$BlocklistDownloadFmt
The format to use when saving automatically downloaded blocklists.
%apply=item id=EnableBlocklistImmediate?%$EnableBlocklistImmediate
Some cookbook recipes update pages with author input but don't use the built-in data posting routines. If $EnableBlocklistImmediate is set (default) and the current action is listed in $BlocklistActions (below), then an immediate blocklist scan is performed on the incoming text.
%apply=item id=BlocklistActions?%$BlocklistActions
A list of actions for which immediate blocklist checks should be performed (see $EnableBlocklistImmediate above).
# perform immediate checks for ?action=comment
$BlocklistActions['comment'] = 1;
# perform immediate checks for ?action=postdata
$BlocklistActions['postdata'] = 1;

Notify

The notify.php script allows a site administrator to configure PmWiki to send email messages whenever pages are changed on the wiki site. Notifications can be configured so that multiple page changes over a short period of time are combined into a single email message (to avoid flooding mailboxes).

This feature is useful for sites and pages that have infrequent updates, as it eliminates the need to frequently check RecentChanges pages just to see if anything has changed.

In order for notifications to work, the notify.php script must be enabled in the site's local customization. Usually this is as simple as placing the following in local/config.php:

Notification configuration

Once enabled, the notification system gets its configuration from the SiteAdmin.NotifyList wiki page. The SiteAdmin.NotifyList page contains entries of the form:

notify=alice@example.com

This says that information about page changes should be periodically emailed to alice@example.com. The SiteAdmin.NotifyList page can contain multiple "notify=" lines to cause notifications to be sent to multiple addresses; the "notify=" lines can be concealed by placing them inside of an (:if false:) conditional section on the page.

NOTE: Do not put any spaces around the equal sign! Notifications will fail silently if you have... This is a really easy mistake to make because all of the other assignments have spaces around the equal sign.

notify=fred@example.com rather than notify = fred@example.com

Notification options

The basic syntax is

notify=email@address name=abc group=def trail=ghi squelch=123 delay=123

A number of options exist for limiting the pages that result in a notification. The group= and name= parameters can be used to restrict notifications to specific pages or groups:

# send notifications about the Main group to alice@example.com
notify=alice@example.com group=Main

# notify bob@example.com of any changes to the home page
notify=bob@example.com name=Main.HomePage
# notify charles@example.com of changes to pages except in Main
notify=charles@example.com group=-Main

(Note: The options are similar to the PageList syntax.)

For maintaining arbitrary lists of pages, i.e., "watchlists", it's generally easier to build a trail of pages to be watched. The following entry in SiteAdmin.NotifyList will send alice@example.com an email containing changes to any of the pages listed in the Profiles.Alice trail:

# notify Alice of changes to pages listed in Profiles.Alice
notify=alice@example.com trail=Profiles.Alice

Note that once this entry has been added to SiteAdmin.NotifyList, Alice can easily change her watchlist by editing the Profiles.Alice page, and doesn't need to edit the SiteAdmin.NotifyList page. In particular, this means that an administrator can restrict editing of SiteAdmin.NotifyList, yet allow individuals to maintain custom watchlists in other pages.

Limitations of this feature:

  • only manually-added links on a trail will be acknowledged by the Notify List (no "group=" or other pagelist syntax, nor any "Group.RecentChanges?" links, will generate notifications)
  • using an (:include:) directive on the page SiteAdmin.NotifyList is not an operational work-around.

This is probably a good place to point out that edit access to SiteAdmin.NotifyList should be controlled, otherwise malicious persons can use the notification capability to flood others' electronic mailboxes. By default, SiteAdmin.NotifyList is blocked against reading or edits except by the admin (as is the case for most pages in the SiteAdmin? group).

Adding notification entries via local customizations

Notification entries can also be added via the $NotifyList array in local/config.php. Simply add a line like the following:

$NotifyList[] = 'notify=alice@example.com group=Main';
$NotifyList[] = 'notify=bob@example.com name=Main.HomePage';

Controlling notification frequency

To prevent flooding of recipients' mailboxes, the notify script uses a "squelch" value as the minimum amount of time that must elapse between messages sent to any given email address. The default squelch setting is 10800 seconds (three hours), which means that once a recipient address is sent a notification message, it will not receive another for at least three hours. Any edits that occur during the squelch interval are queued for the next notification message.

The site administrator can change the default squelch interval via the $NotifySquelch parameter

# enable notifications
$NotifySquelch = 86400; # wait at least one day (in seconds) between notifications

In addition, individual addresses can specify a custom squelch parameter in the SiteAdmin.NotifyList page:

# Alice receives at most one email per day
notify=alice@example.com squelch=86400
# Bob can get notifications hourly
notify=bob@example.com trail=Profiles.Bob squelch=3600
# Charles uses the site default squelch
notify=charles@example.com

Controlling notification delay

Because a page will often receive several edits in rapid succession (e.g., a long post followed by several minor edits), a site administrator can also set a $NotifyDelay value that specifies how long to wait after an initial post before sending notifications:

# enable notifications
$NotifySquelch = 86400; # wait at least one day between notifications
$NotifyDelay = 300; # wait five minutes after initial post

Note that the squelch and delay values are minimums; notifications are sent on the first execution of PmWiki after the delay period has expired. For inactive sites, this could be much longer than the specified delay periods. This isn't really considered an issue since timely notifications are less important on relatively inactive sites. However, changes within the squelch time after the last notification will remain unnoticed if the wiki is not even visited for a long period after. If this matters it might be necessary to make the server call pmwiki.php regularly (e.g. cron job).

Custom delay parameters cannot be specified for individual addresses in the SiteAdmin.NotifyList page:

# the delay= parameter will be ignored
notify=edgar@example.com trail=Profiles.Edgar delay=600

Note for Windows installations

Sites running PHP under Windows may not have PHP's mail function configured correctly. Such sites may need to add a line like

ini_set('SMTP','smtp.server.com');

to config.php, where smtp.server.com is the name of your host's preferred outgoing mail server. You may also need to set the sendmail_from value if that is not configured:

ini_set('sendmail_from','noreply@foo.com');

Notify Variables

%apply=item id=EnableNotify?%$EnableNotify
Tells stdconfig.php to enable the notify script.
$EnableNotify = 1; # enable notify
$EnableNotify = 0; # disable notify
%apply=item id=NotifyFrom?%$NotifyFrom
Return email address to be used in the sent email.
$NotifyFrom = 'wiki@example.com';
$NotifyFrom = 'Wiki server <wiki@example.com>';
%apply=item id=NotifyDelay?%$NotifyDelay
The length of time (seconds) to wait before sending mail after the first post. Defaults to zero - posts are sent as soon as any squelch period has expired.
$NotifyDelay = 300; # send mail 5+ min after first post
%apply=item id=NotifySquelch?%$NotifySquelch
The default minimum time (seconds) that must elapse between sending mail messages. Useful when $NotifyDelay is set to a small value to keep the number of mail notification messages down. Defaults to 10800 (three hours). Individual recipients can override this value in the SiteAdmin.NotifyList page.
$NotifySquelch = 43200; # wait 12+ hours between mailings
%apply=item id=NotifyItemFmt?%$NotifyItemFmt
The text to be sent for each changed item in the post. The string "$PostTime" is substituted with the time of the post (controlled by $NotifyTimeFmt below).
# default
$NotifyItemFmt = ' * $FullName . . . $PostTime by $Author';
# include the page's URL in the message
$NotifyItemFmt =
" * \$FullName . . . \$PostTime by \$Author\n \$PageUrl";
# include the change summary and link to the page's history in the message
$NotifyItemFmt =
" * {\$FullName} . . . \$PostTime by {\$Author}
\n Summary: {\$LastModifiedSummary}\n {\$PageUrl}?action=diff";
%apply=item id=NotifyTimeFmt?%$NotifyTimeFmt
The format for dates/times in $PostTime above. Defaults to the value of $TimeFmt.
$NotifyTimeFmt = '%Y-%m-%d %H:%M'; # 2004-03-20 17:44
%apply=item id=NotifyBodyFmt?%$NotifyBodyFmt
The body of the message to be sent. The string "$NotifyItems" is replaced with the list of posts (as formatted by $NotifyItemFmt above). Use single quotation marks ' to prevent substring "$NotifyItems" from being untimely evaluated as variable in config.php.
$NotifyBodyFmt = "Changed items:\n\n" . '$NotifyItems' . "\n\n Best regards...";
%apply=item id=NotifySubjectFmt?%$NotifySubjectFmt
The subject line of the mail to be sent.
%apply=item id=NotifyHeaders?%$NotifyHeaders
String of extra mail headers to be passed to the mail() function.
%apply=item id=NotifyParameters?%$NotifyParameters
String of additional parameters to be passed to PHP's mail() function [8].
%apply=item id=NotifyFile?%$NotifyFile
The scratch file where Notify keeps track of recent posting information. Defaults to "$WorkDir/.notifylist". Note that this file must generally be writable by the webserver process.
%apply=item id=NotifyListPageFmt?%$NotifyListPageFmt
The name of the page containing notify= lines for use by notify.php. Defaults to $SiteAdminGroup.NotifyList.
%apply=item id=NotifyList?%$NotifyList
An array of notify= specifications that can be specified from a local customization file (used in addition to entries in SiteAdmin.NotifyList).
# send notifications to alice@example.com
$NotifyList[] = 'notify=alice@example.com';
%apply=item id=EnableNotifySubjectEncode?%$EnableNotifySubjectEncode
Apply a standard (base64) encoding for the e-mail subject. Notify e-mails from international wikis may otherwise have unreadable subjects (added for version 2.2.2).
$EnableNotifySubjectEncode = 1; # encode subject
$EnableNotifySubjectEncode = 0; # use subject as is (default)
To fix encodings with the message body, add to config.php the following line (after XLPage? and/or UTF-8):
$NotifyHeaders = "Content-type: text/plain; charset=$Charset";

Notification only for major edits

It is possible to send notifications only in case of major edits. In your config.php, replace "$EnableNotify=1;" with the following:

if ( @$_POST['diffclass'] != 'minor' ) $EnableNotify=1;

This way, only 'major' edits send notify messages (when the author doesn't select the checkbox for minor edit). If you want minor edits and not major edits to send the message then you would use:

if ( @$_POST['diffclass'] == 'minor' ) $EnableNotify=1;

instead.

Disabling notifications for downloads

If you use "$EnableDirectDownloads=0;" (eg. for privacy on a password-protected wiki) then attached images may generate duplicate notification messages. To prevent that disable notifications for downloads via

if ( $action != 'download' ) $EnableNotify=1;

That way, only page views (and not images within the page) will generate notifications. See PITS:01159 for more information.


PasswordsAdmin

PmWiki has built-in support for password-protecting various areas of the wiki site. Passwords can be applied to individual pages, to Wiki Groups, or to the entire wiki site. Note that the password protection mechanisms described here are only a small part of overall system (and wiki) security, see PmWiki.Security for more discussion of this.

Authors can use PmWiki to add passwords to individual pages and WikiGroups as described in Passwords. However, WikiAdministrators can also set passwords in local/config.php as described below. (Please note that one cannot set passwords reliably in per group or per page customization files. See the FAQ section for details.)

Password basics

PmWiki supports several levels of access to wiki pages, known as authorisation level:

  • read passwords allow viewing the contents of wiki pages
  • edit passwords control editing and modification of wiki pages (effective against spam)
  • attr passwords control who is able to set passwords on pages (and potentially other future attributes)
  • upload password, if uploads are enabled, controls uploading of files and attachments
  • in addition all available actions can be password authorised
  • admin password allows an administrator to override the passwords set for any individual page or group.

By default, PmWiki has the following password settings:

  • The admin and upload passwords are locked by default.
  • The Main and PmWiki groups have a locked attr password (in their respective GroupAttributes pages).
  • The pages in the Site group except Site.SideBar are locked against editing; by default the Site.SideBar page requires the admin or the site-wide edit password.

An admin password can be used to overcome "locked" passwords, other than that, no password will allow access.

See Passwords for information about setting per-page and per-group passwords. The remainder of this page describes setting site-wide passwords from the local/config.php file.

Setting site-wide passwords

One of the first things an admin should do is set an admin password for the site. This is done via a line like the following in the local/config.php file:

$DefaultPasswords['admin'] = crypt('secret_password');

Note that the crypt() call is required for this -- PmWiki stores and processes all passwords internally as encrypted strings. See the crypt section below for details about eliminating the cleartext password from the configuration file.

To set the entire site to be editable only by those who know an "edit" password, add a line like the following to local/config.php:

$DefaultPasswords['edit'] = crypt('edit_password');

Similarly, you can set a password for any available action, viz $DefaultPasswords['read'], $DefaultPasswords['edit'], and $DefaultPasswords['upload'] to control default read, edit, and upload passwords for the entire site. The default passwords are used only for pages and groups which do not have passwords set. Also, each of the $DefaultPasswords values may be arrays of encrypted passwords:

$DefaultPasswords['read'] = array(crypt('alpha'), crypt('beta'));
$DefaultPasswords['edit'] = crypt('beta');

This says that either "alpha" or "beta" can be used to read pages, but only the "beta" password will allow someone to edit a page. Since PmWiki remembers any passwords entered during the current session, the "beta" password will allow both reading and writing of pages, while the "alpha" password allows reading only. A person without either password would be unable to view pages at all.

Setting passwords by reference

Setting passwords by reference allows you to change the password for a whole set of pages as easily as you can change site-wide passwords. (Otherwise you would have to update each page's attributes individually.) Enter in the Page Attributes or Group Attributes:

@_site_MyPassword2

And in the local configuration file set the actual password with lines like this:

$DefaultPasswords['MyPassword2?'] = array(crypt('secret'), '@admins');
$DefaultPasswords['MyPassword9?'] = array('$1$NuBV/Mcc$GG3J60h.TLczUTRKhoVPM?.');

Identity-based authorization (username/password logins, AuthUser)

Unlike many systems which have identity-based systems for controlling access to pages (e.g., using a separate username and password for each person), PmWiki defaults to a password-based system as described above. In general password-based systems are often easier to maintain because they avoid the administrative overheads of creating user accounts, recovering lost passwords, and mapping usernames to permitted actions.

However, PmWiki's authuser.php script augments the password-based system to allow access to pages based on a username and password combination. See AuthUser for more details on controlling access to pages based on user identity.

Security holes ...

Administrators need to carefully plan where passwords are applied to avoid opening inadvertent security holes. If your wiki is open (anyone can read and edit), this would not seem to be a concern, except, a malicious or confused user could apply a read password to a group and make the group completely unavailable to all other users. At the very least, even an open wiki should have a site-wide "admin" password and a site-wide "attr" password set in config.php. The sample-config.php file distributed with PmWiki indicates that the PmWiki and Main groups have "attr" locked by default, but if anyone creates a new group, "attr" is unlocked. Administrators must remember to set "attr" passwords for each new group (if desired) in this case. An easier solution is to include these lines in config.php :

$DefaultPasswords['admin'] = crypt('youradminpassword');
$DefaultPasswords['attr'] = crypt('yourattrpassword');

Encrypting passwords in config.php

One drawback to using the crypt() function directly to set passwords in config.php is that anyone able to view the file will see the unencrypted password. For example, if config.php contains

$DefaultPasswords['admin'] = crypt('mysecret');

then the "mysecret" password is in plain text for others to see. However, a wiki administrator can obtain and use an encrypted form of the password directly by using ?action=crypt on any PmWiki url (or just jump to IncludeAll?action=crypt). This action presents a form that generates encrypted versions of passwords for use in the config.php file. For example, when ?action=crypt is given the password "mysecret", PmWiki will return a string like

$1$hMMhCdfT$mZSCh.BJOidMRn4SOUUSi1

The string returned from ?action=crypt can then be placed directly into config.php, as in:

$DefaultPasswords['admin'] = '$1$hMMhCdfT$mZSCh.BJOidMRn4SOUUSi1';

Note that in the encrypted form the crypt keyword and parentheses are removed, since the password is already encrypted. Also, the encrypted password must be in single quotes. In this example the password is still "mysecret", but somebody looking at config.php won't be able to see that just from looking at the encrypted form. Crypt may give you different encryptions for the same password--this is normal (and makes it harder for someone else to determine the original password).

Removing passwords

To remove a site password entirely, such as the default locked password for uploads, just set it to empty:

$DefaultPasswords['upload'] = '';

You can also use the special password "@nopass" via ?action=attr to have a non-password protected page within a password-protected group, or a non-password protected group with a site-wide default password set.

Revoking or invalidating passwords

If a password is compromised and the wiki administrator wants to quickly invalidate all uses of that password on a site, a quick solution is the following in local/config.php:

$ForbiddenPasswords = array('secret', 'tanstaafl');
if (in_array(@$_POST['authpw'], $ForbiddenPasswords)) 
  unset($_POST['authpw']);

This prevents "secret" and "tanstaafl" from ever being accepted as a valid authorization password, regardless of what pages may be using it.

See Also

Protecting actions (example)

Each action can be password protected. Cookbook authors providing scripts with own actions can use this also, but I'll limit the example to a (by default) not protected ?action=source. This action shows the wikisource of the actual page. Sometimes you don't want that especially to Cookbook:protect email or when using some conditional markup which should not be discovered easily or only by persons that are allowed to edit the page.

There are several solutions for that:

  1. Limit "source" only to editors add the following to your local/config.php:
    $HandleAuth['source'] ='edit';
  2. For using "source" with an own password, then add:
    $HandleAuth['source'] ='source';
    $DefaultPasswords['source'] = crypt('secret'); # see above

If you additionally want to set the password in the attributes page add:

$PageAttributes['passwdsource'] = "$['Set new source password']";

In general, adding the prefix 'passwd' to an action name in the $PageAttributes array indicates that you wish for the given field to be encrypted when saved to disk.

The full set of steps to add new password handling for an action such as "diff" would be:

# add a new (encrypted) field to the attr page
$PageAttributes['passwddiff'] = '$[Set new history password:]';

# clear the default password for 'diff'
$DefaultPasswords['diff'] = '';

# Tell PmWiki that the 'diff' password allows action 'diff'.
$HandleAuth['diff'] = 'diff';

# Tell PmWiki that a 'read' password 
# (or optionally the 'edit') password
# is also sufficient to enable 'diff'.
# Of course, the 'admin' password will work too.
$AuthCascade['diff'] = 'read';    ## or 'edit'

There seems to be a default password. What is it?

There isn't any valid password until you set one. Passwords admin describes how to set one.

PmWiki comes "out of the box" with $DefaultPasswords['admin'] set to '*'. This doesn't mean the password is an asterisk, it means that default admin password has to be something that encrypts to an asterisk. Since it's impossible for the crypt() function to ever return a 1-character encrypted value, the admin password is effectively locked until the admin sets one in config.php.

How do I use passwd-formatted files (like .htpasswd) for authentication?

See AuthUser, Cookbook:HtpasswdForm or Cookbook:UserAuth.

Is there anything I can enter in a GroupAttributes field to say 'same as the admin password'? If not, is there anything I can put into the config.php file to have the same effect?

Enter '@lock' in GroupAttributes?action=attr to require an admin password for that group.

How do I edit protect, say, all RecentChanges pages?

see Security#wikivandalism.

How can I read password protect all pages in a group except the HomePage using configuration files?

As described in PmWiki.GroupCustomizations per-group or per-page configuration files should not be used for defining passwords. The reason is that per-group (or per-page) customization files are only loaded for the current page. So, if $DefaultPasswords['read'] is set in GroupA?.php, then someone could use a page in another group to view the contents of pages in GroupA?. For example, Main.WikiSandbox could contain:

(:include GroupA.SomePage:)

and because the GroupA?.php file wasn't loaded (we're looking at Main.WikiSandbox --> local/Main.php), there's no read password set.

How can I password protect the creation of new pages?

See Cookbook:LimitWikiGroups, Cookbook:NewGroupWarning, Cookbook:LimitNewPagesInWikiGroups.

How do I change the password prompt screen?

If your question is about how to make changes to that page... edit Site.AuthForm. If your question is about how to change which page you are sent to when prompted for a password, you might check out the Cookbook:CustomAuthForm for help.

How do I change the prompt on the attributes (?action=attr) screen?

Simply create a new page at Site.AttrForm?, and add the following line of code to config.php:

$PageAttrFmt = 'page:Site.AttrForm?';

Note that this only changes the text above the password inputs on the attributes page, but doesn't change the inputs themselves - the inputs have to be dealt with separately. See Cookbook:CustomAttrForm for more info.

I get http error 500 "Internal Server Error" when I try to log in. What's wrong?

This can happen if the encrypted passwords are not created on the web server that hosts the PmWiki.
The crypt function changed during the PHP development, e.g. a password encrypted with PHP 5.2 can not be decrypted in PHP 5.1, but PHP 5.2 can decrypt passwords created by PHP 5.1.
This situation normally happens if you prepare everything on your local machine with the latest PHP version and you upload the passwords to a webserver which is running an older version.
The same error occurs when you add encrypted passwords to local/config.php.

Solution: Create the passwords on the system with the oldest PHP version and use them on all other systems.

I only want users to have to create an 'edit' password, which is automatically used for their 'upload' & 'attr' passwords (without them having to set those independently). How do I do this?

By setting $HandleAuth like so:

      $HandleAuth['upload'] = 'edit';
      // And to prevent a WikiSandbox from having it's 'attr' permissions changed 
      // except by the admin (but allowing editors to change it on their own pages/group)
      if(($group=="Site") || ($group=="Main") || ($group=="Category") || 
             ($group=="SiteAdmin?") || ($group=="PmWiki") ) {
	$HandleAuth['attr'] = 'admin';  // for all main admin pages, set 'attr' to 'admin' password
      } else { 
	$HandleAuth['attr'] = 'edit';  // if you can edit, then you can set attr
      }

RefCount

RefCount performs link reference counts on pages in the PmWiki database (i.e., counts of links between pages). Before using RefCount, it must be enabled by the wiki administrator by placing the following line in a local customization file:

include_once("$FarmD/scripts/refcount.php");

To use refcount add ?action=refcount to the URL of any wiki page to bring up the reference count form. For example:

The refcount form contains the following controls:

  • Show ~ This selects which pages will appear in the output
    • all ~ Shows all references
    • missing ~ Shows only references to pages that don't exist
    • existing ~ Shows only references to pages that do exist
    • orphaned ~ Shows pages that exist but don't have any references to them. There is no way to browse to an orphaned page.
  • page names in group ~ Selects which group(s) to the referenced pages can be in
  • referenced from pages in ~ Selects which group(s) the referencing pages can be in
  • Display referencing pages ~ Includes a link to the referencing page -- this can make for a very long output unless you limit the groups searched

The output is a table where each row of the table contains a page name or link reference, the number of (non-RecentChanges) pages that contain links to the page and the number of Recent Changes pages with links to the page.


UrlApprovals

This page explains how to discourage "link spamming" on your wiki site using PmWiki's urlapprove.php script. This script is already included in PmWiki files, but not activated by default.

Using urlapprove.php

Occasionally spammers may try to add large number of (sometimes hidden) URLs to pages because they think it will improve their search engine rankings -- which it probably won't. The urlapprove.php script works against these spammers' purpose by

  • requiring approval of links to Internet sites before a link to them are created in the wiki, and
  • allowing you to limit the number of unapproved links that may be added to a page.

To enable urlapprove.php, add the following line to a configuration file:

include_once("$FarmD/scripts/urlapprove.php");

By default, unapproved links display what ever should be displayed normally (the URL or a text), but not linked and next to it a link (approve links). A click on the link will approve all unapproved URLs on the page, but only if you are authorized to edit the SiteAdmin.ApprovedUrls page. You may also pre-approve sites by by adding them directly to the SiteAdmin.ApprovedUrls page.

Limiting unapproved urls per page

You can limit the number of unapproved links per page. If the limit is exceeded, the page cannot be saved. This is useful because spammers like to write long link lists, which is rare for normal authors.

Example: To set the limit to 5 unapproved links, add the following line to a configuration file:

$UnapprovedLinkCountMax = 5;
include_once('scripts/urlapprove.php');

Note that $UnapprovedLinkCountMax must be set before including the urlapprove.php script.

Handling of Unapproved Links

You can also change the disapproval message defined in the $UnapprovedLinkFmt variable, for example:

include_once('scripts/urlapprove.php');
$UnapprovedLinkFmt =
 "[$[Link requires approval]]<a class='apprlink'
  href='\$PageUrl?action=approvesites'>$[(approve)]</a>";

"Link requires approval" is whatever you want to see in place of the unapproved link and "(approve)" is the blue text. Using this feature may prove usefull if you want to always hide the unapproved link.

If you wish to totally forbid unapproved links you can use

$UnapprovedLinkFmt = "<b>external link not allowed</b>";

SideBar caveat

Please note that in general you need to go to the sidebar page in order to approve links in the sidebar. The reason for this is that the approve mechanism only approves links on the current page.

Initial setup

After initial setup all existing links become unapproved. You need to visit your pages and approve all links, where needed. See AllRecentChanges for a list of all pages that were created on your wiki.

Password approval of URLs?

To approve external links, an author needs permissions to edit the page SiteAdmin.ApprovedUrls.

Technical tips

URL Whitelist

Urls can also be approved by adding them to a "white list", defined in the variable $WhiteUrlPatterns, which is set in the local/config.php file.
To add multiples urls, use the separator | (vertical bar). For example:

$WhiteUrlPatterns =
  "(http://example.com|http://example.net|http://example.org)";

To add all urls from, say New Zealand and Australia, use:

$WhiteUrlPatterns[] = 'http://[^/]+\\.nz';
$WhiteUrlPatterns[] = 'http://[^/]+\\.au';

Change Approved URLs? page name

If you want to change the default name of SiteAdmin.ApprovedUrls, set the following in local/config.php:

$ApprovedUrlPagesFmt = array('OtherGroup.OtherName');

Previewing the unapproved URL

To see what link is to be approved without editing the page a tool tip can be displayed when the cursor hovers over the (approve links) link that displays the URL. e.g. [(approve links) edit diff].

Add the following setting in your local/config.php:

$UnapprovedLinkFmt =
  "\$LinkText<a class='apprlink' href='\$PageUrl?action=approvesites'
   title='\$LinkUrl'>$[(approve links)]</a>";
Some browsers show only the link and not the tooltip title. In this case, you can use the following code to see the unapproved link at the end of the tooltip :
$UnapprovedLinkFmt =
  "\$LinkText<a class='apprlink' href='\$PageUrl?action=approvesites&XES_url=\$LinkUrl'
   title='\$LinkUrl'>$[(approve sites)]</a>";

About rel='nofollow'

By default, PmWiki creates external links that are not followed by search engines. Here are release notes from pmwiki-2.0.beta20 (30-Jan-2005):

First, the $UrlLinkFmt variable has been modified so that links to external urls automatically have a rel='nofollow' attribute added to them, to help combat wiki spam as described in http://googleblog.blogspot.com/2005/01/preventing-comment-spam.html. Site administrators can customize $UrlLinkFmt and $UnapprovedLinkFmt to supply or omit rel='nofollow' as appropriate.

See Also


Variables


List of documented PHP variables

VariableDocumented in
$AbortFunctionDebugVariables
$ActionSkinLayoutVariables
$ActionTitleFmtLayoutVariables
$AddLinkCSSLinkVariables
$AllowPasswordSecurityVariables
$AsSpacedFunctionBasicVariables
$AuthFormRespCodeSecurityVariables
$AuthIdBasicVariables
$AuthLDAPBindDNSecurityVariables
$AuthLDAPBindPasswordSecurityVariables
$AuthLDAPReferralsSecurityVariables
$AuthorBasicVariables
$AuthorGroupBasicVariables
$AuthPwBasicVariables
$AuthUserPageFmtSecurityVariables
$AutoCreateEditVariables
$BaseNameBasicVariables
$BaseNamePatternsBasicVariables
$CategoryGroupBasicVariables
$CookiePrefixBasicVariables
$CookieSameSiteSecurityVariables
$CurrentLocalTimeLayoutVariables
$CurrentTimeLayoutVariables
$CustomSyntaxLayoutVariables
$DefaultEmptyPageTextVarsOtherVariables
$DefaultGroupBasicVariables
$DefaultNameBasicVariables
$DefaultPageBasicVariables
$DefaultPageCharsetI18nVariables
$DefaultPageTextFmtEditVariables
$DefaultPasswordsSecurityVariables
$DefaultUnsetPageTextVarsOtherVariables
$DeleteKeyPatternEditVariables
$DenyHtaccessContentSecurityVariables
$DiffKeepDaysEditVariables
$DiffKeepNumEditVariables
$DraftActionsPatternEditVariables
$DraftRecentChangesFmtLayoutVariables
$DraftSuffixEditVariables
$EditFunctionsEditVariables
$EditRedirectFmtEditVariables
$EditTemplatesFmtEditVariables
$EnableAutoSkinListLayoutVariables
$EnableBaseNameConfigBasicVariables
$EnableCommonEnhancementsBasicVariables
$EnableCookieHTTPOnlySecurityVariables
$EnableCookieSecureSecurityVariables
$EnableCopyCodeLayoutVariables
$EnableCreoleOtherVariables
$EnableDarkThemeToggleLayoutVariables
$EnableDiagDebugVariables
$EnableDiffInlineLayoutVariables
$EnableDirectDownloadUploadVariables
$EnableDownloadRangesUploadVariables
$EnableDraftAtomicDiffEditVariables
$EnableDraftsEditVariables
$EnableEditAutoTextEditVariables
$EnableFeedsOtherVariables
$EnableFixedUrlRedirectLayoutVariables
$EnableFTimeNewBasicVariables
$EnableGUIButtonsEditVariables
$EnableGuiEditFixUrlEditVariables
$EnableHighlightLayoutVariables
$EnableIMSCachingDebugVariables
$EnableInputDataAttrOtherVariables
$EnableLinkPageRelativeLinkVariables
$EnableLinkPlusTitlespacedLinkVariables
$EnableListIncludedPagesEditVariables
$EnableLocalConfigBasicVariables
$EnableLocalTimesLayoutVariables
$EnableMarkupDiagDebugVariables
$EnableMergeLastMinorEditEditVariables
$EnableNotifyNotify
$EnableNotifySubjectEncodeNotify
$EnableNotSavedWarningEditVariables
$EnableObfuscateEmailsLinkVariables
$EnablePageIndexPagelistVariables
$EnablePageListProtectPagelistVariables
$EnablePageTitlePriorityLayoutVariables
$EnablePageVarAuthSecurityVariables
$EnablePathInfoLayoutVariables
$EnablePGCustBasicVariables
$EnablePmFormOtherVariables
$EnablePmSyntaxLayoutVariables
$EnablePmUtilsLayoutVariables
$EnablePostAttrClearSessionSecurityVariables
$EnablePostAuthorRequiredEditVariables
$EnablePreserveLineBreaksLayoutVariables
$EnablePreviewChangesEditVariables
$EnablePublishAttrSecurityVariables
$EnableRCDiffBytesLayoutVariables
$EnableReadOnlyEditVariables
$EnableRecentUploadsLayoutVariables
$EnableRedirectBasicVariables
$EnableRedirectQuietLinkVariables
$EnableRefCountOtherVariables
$EnableRelativePageVarsBasicVariables
$EnableRevUserAgentEditVariables
$EnableRobotCloakActionsSecurityVariables
$EnableROSEscapeEditVariables
$EnableSearchAtLeastOneTermPagelistVariables
$EnableSelfWikiPageCSSLayoutVariables
$EnableSessionPasswordsSecurityVariables
$EnableSimpleTableRowspanLayoutVariables
$EnableSortableLayoutVariables
$EnableStdConfigBasicVariables
$EnableStopWatchDebugVariables
$EnableTableAutoValignTopLayoutVariables
$EnableUndefinedTemplateVarsPagelistVariables
$EnableUploadUploadVariables
$EnableUploadAuthorRequiredEditVariables
$EnableUploadDropUploadVariables
$EnableUploadGroupAuthUploadVariables
$EnableUploadMimeMatchUploadVariables
$EnableUploadOverwriteUploadVariables
$EnableUploadVersionsUploadVariables
$EnableUrlApproveOtherVariables
$EnableWikiWordsBasicVariables
$EnableWSPreBasicVariables
$EnableXLPageScriptLoadI18nVariables
$FailedLoginsFunctionSecurityVariables
$FarmDPathVariables
$FarmPubDirUrlPathVariables
$FmtPOtherVariables
$FmtPVOtherVariables
$FmtVOtherVariables
$FPLTemplatePageFmtPagelistVariables
$FTimeFmtBasicVariables
$GroupFooterFmtLayoutVariables
$GroupHeaderFmtLayoutVariables
$GroupPatternBasicVariables
$GroupPrintFooterFmtLayoutVariables
$GroupPrintHeaderFmtLayoutVariables
$GUIButtonsEditVariables
$HandleAuthSecurityVariables
$HandleEditFmtEditVariables
$HTMLFooterFmtLayoutVariables
$HTMLHeaderFmtLayoutVariables
$HTMLPNewlineLayoutVariables
$HTMLStylesFmtLayoutVariables
$HTMLTagAttrLayoutVariables
$HTMLTitleFmtLayoutVariables
$HTMLVSpaceLayoutVariables
$IMapLinkFmtLinkVariables
$ImgDarkSuffixUploadVariables
$InputLabelFmtLayoutVariables
$InterMapFilesLinkVariables
$IsPagePostedEditVariables
$LinkCategoryFmtLinkVariables
$LinkPageCreateFmtLinkVariables
$LinkPageCreateSpaceFmtLinkVariables
$LinkPageExistsFmtLinkVariables
$LinkPageSelfFmtLinkVariables
$LinkUploadCreateFmtUploadVariables
$LinkWikiWordsBasicVariables
$LocalDirPathVariables
$LogoutCookiesBasicVariables
$LogoutRedirectFmtBasicVariables
$MailFunctionNotify
$MakePageNameFunctionLinkVariables
$MakePageNamePatternsLinkVariables
$MakePageNameSplitPatternLinkVariables
$MakeUploadNamePatternsUploadVariables
$MarkupDirectiveFunctionsOtherVariables
$MarkupMarkupLevelOtherVariables
$MaxIncludesLayoutVariables
$MaxPageTextVarsOtherVariables
$MessagesFmtLayoutVariables
$MetaRobotsLayoutVariables
$MultiFactorAuthFunctionSecurityVariables
$NamePatternBasicVariables
$NotifyBodyFmtNotify
$NotifyDelayNotify
$NotifyFileNotify
$NotifyFromNotify
$NotifyHeadersNotify
$NotifyItemFmtNotify
$NotifyListNotify
$NotifyListPageFmtNotify
$NotifyParametersNotify
$NotifyRelatedTrailFmtNotify
$NotifySquelchNotify
$NotifySubjectFmtNotify
$NotifyTimeFmtNotify
$PageAttributesSecurityVariables
$PageCacheDirOtherVariables
$PageCSSListFmtPathVariables
$PageEditFmtEditVariables
$PageEditFormEditVariables
$PageIndexFilePagelistVariables
$PageIndexFoldFunctionPagelistVariables
$PageIndexTermsFunctionPagelistVariables
$PageListCacheDirPagelistVariables
$PageListSortCmpFunctionPagelistVariables
$PageListVarFoldFnPagelistVariables
$PageLogoUrlLayoutVariables
$pagenameBasicVariables
$PageNotFoundHeaderFmtLayoutVariables
$PagePathFmtBasicVariables
$PageRedirectFmtLayoutVariables
$PageSearchFormPagelistVariables
$PageSkinListLayoutVariables
$PmTOCLayoutVariables
$PubDirUrlPathVariables
$QualifyPatternsLinkVariables
$RCLinesMaxLayoutVariables
$RecentChangesFmtLayoutVariables
$RecentUploadsFmtLayoutVariables
$RobotActionsSecurityVariables
$RobotPatternSecurityVariables
$ROEPatternsEditVariables
$ROSPatternsEditVariables
$ScriptUrlPathVariables
$SearchBoxInputTypePagelistVariables
$SearchBoxOptPagelistVariables
$SearchPatternsPagelistVariables
$SessionDecodeSecurityVariables
$SessionEncodeSecurityVariables
$SetCookieFunctionSecurityVariables
$SimpleTableDefaultClassNameLayoutVariables
$SiteAdminGroupBasicVariables
$SiteGroupBasicVariables
$SkinBasicVariables
$SkinDirPathVariables
$SkinDirUrlPathVariables
$SkinLibDirsLayoutVariables
$SkinTemplateIncludeLevelLayoutVariables
$SpaceWikiWordsBasicVariables
$TableCellAlignFmtLayoutVariables
$TableCellAttrFmtLayoutVariables
$TableRowAttrFmtLayoutVariables
$TableRowIndexMaxLayoutVariables
$TimeFmtBasicVariables
$ToggleNextSelectorLayoutVariables
$TrailFmtLayoutVariables
$TrailPathSepLayoutVariables
$TROEPatternsEditVariables
$UploadBlacklistUploadVariables
$UploadBlockPatternsUploadVariables
$UploadDirUploadVariables
$UploadDirQuotaUploadVariables
$UploadExtsUploadVariables
$UploadExtSizeUploadVariables
$UploadMaxSizeUploadVariables
$UploadNameCharsUploadVariables
$UploadPermAddUploadVariables
$UploadPermSetUploadVariables
$UploadPrefixFmtUploadVariables
$UploadPrefixQuotaUploadVariables
$UploadRedirectFunctionUploadVariables
$UploadUrlFmtUploadVariables
$UrlLinkFmtLinkVariables
$UrlSchemePathVariables
$VarPagesFmtI18nVariables
$VersionBasicVariables
$VersionNumBasicVariables
$WikiDirPathVariables
$WikiLibDirsPathVariables
$WikiPageCSSFmtLayoutVariables
$WikiPageCSSVarsLayoutVariables
$WikiStyleLayoutVariables
$WikiStyleApplyLayoutVariables
$WikiTitleLayoutVariables
$WikiWordCountLinkVariables
$WikiWordCountMaxLinkVariables
$WikiWordPatternBasicVariables
$WorkDirPathVariables
$XLLangsI18nVariables
where is this documented?

This page documents the PHP variables available in PmWiki for local customizations. Much of this documentation is still incomplete but people are working on it now. Feel free to add placeholders for variables you want to have documented if you don't know what the variable does.

The variables documentation is divided into several pages:

The following functions are also controlled by several variables:

The following variables are used in page markup.

  • Page Variables - variables that are associated with pages
  • Page TextVariables - Testing the functionality of page text variables, especially leading and trailing spaces, and construction of variable names

An complete index of documented PHP variables is given below.

In general, variables with names ending in 'Fmt' (such as $PageLayoutFmt) have their values processed for $-variable substitutions prior to being output. Thus strings such as {$Name} and {$PageUrl} are replaced with the name and URL of the page when the string is printed.

Note: The automatic variable index and link generation is done by scripts/vardoc.php using $VarPagesFmt to find the pages containing trails of pages with the variable documentation.

There is a slight discrepancy between index generation and link generation: The index generation finds lines starting with a colon followed by "$" and an uppercase word. In contrast, the automatic link generation works only with WikiWords ($WikiWordPattern) preceded by "$". Therefore all "non WikiWord" variables are shown as link only in the list below, but not elsewhere in PmWiki, as $Author, $Version and $XL.

See Also

  • Functions - How some of the functions in pmwiki.php work

Categories: PmWiki Developer


Functions

This page describes some of the internal workings of PmWiki by explaining how some of the functions in pmwiki.php work. For a more brief list/overview on functions useful to for instance cookbook writers, see Cookbook:Functions.

To use this functions you have to make sure that all relevant internal variables have been initialized correctly. See Custom Markup and Custom Actions for more information on how these functions are typically called via Markup() or $HandleActions[].

PSS($string)

The PSS() function removes the backslashes that are automatically inserted in front of quotation marks by the /e option of PHP's preg_replace function. PSS() is most commonly used in replacement arguments to Markup(), when the pattern specifies /e and one or more of the parenthesized subpatterns could contain a quote or backslash. ("PSS" stands for "PmWiki Strip Slashes".)

From PM: PmWiki expects PSS() to always occur inside of double-quoted strings and to contain single quoted strings internally. The reason for this is that we don't want the $1 or $2 to accidentally contain characters that would then be interpreted inside of the double-quoted string when the PSS is evaluated.
Markup('foo', 'inline', '/(something)/e', 'Foo(PSS("$1"))'); # wrong
Markup('foo', 'inline', '/(something)/e', "Foo(PSS('$1'))"); # right

Example

This is a fictitious example where PSS() should be used. Let us assume that you wish to define a directive (:example:) such that (:example "A horse":) results in the HTML

<div>"A horse"</div>.

Here is how the markup rule can be created:

Markup('example', 'directives',
       '/\\(:example\\s(.*?):\\)/e',
       "Keep('<div>'.PSS('$1').'</div>')");

We need to use PSS() around the '$1' because the matched text could contain quotation marks, and the /e will add backslashes in front of them.

stripmagic($string)

This function should be used when processing the contents of $_POST or _GET variables when they could contain quotes or backslashes. It verifies get_magic_quotes(), if true, strips the automatically inserted escapes from the string.

FmtPageName($fmt, $pagename)

Returns $fmt, with $variable and $[internationalisation] substitutions performed, under the assumption that the current page is pagename. See PmWiki.Variables for an (incomplete) list of available variables, PmWiki.Internationalizations for internationalisation. Security: not to be run on user-supplied data.

This is one of the major functions in PmWiki, see PmWiki.FmtPageName for lots of details.

Markup($name, $when, $pattern, $replace)

Adds a new markup to the conversion table. Described in greater detail at PmWiki.CustomMarkup.

This function is used to insert translation rules into the PmWiki's translation engine. The arguments to Markup() are all strings, where:

$name
The string names the rule that is inserted. If a rule of the same name already exists, then this rule is ignored.
$when
This string is used to control when a rule is to be applied relative to other rules. A specification of "<xyz" says to apply this rule prior to the rule named "xyz", while ">xyz" says to apply this rule after the rule "xyz". See CustomMarkup for more details on the order of rules.
$pattern
This string is a regular expression that is used by the translation engine to look for occurences of this rule in the markup source.
$replace
This string will replace the matched text when a match occurs.

Also see: PmWiki.CustomMarkup and Cookbook:Functions#Markup

MarkupToHTML($pagename, $str)

Converts the string $str containing PmWiki markup into the corresponding HTML code, assuming the current page is $pagename.

Also see: Cookbook:Functions#MarkupToHTML

mkdirp($dir)

The function mkdirp($dir) creates a directory, $dir, if it doesn't already exist, including any parent directories that might be needed. For each directory created, it checks that the permissions on the directory are sufficient to allow PmWiki scripts to read and write files in that directory. This includes checking for restrictions imposed by PHP's safe_mode setting. If mkdirp() is unable to successfully create a read/write directory, mkdirp() aborts with an error message telling the administrator the steps to take to either create $dir manually or give PmWiki sufficient permissions to be able to do it.

MakeLink($pagename, $target, $txt, $suffix, $fmt)

The function MakeLink($pagename, $target, $txt, $suffix, $fmt) returns a ???. Its arguments are as follows:

 $pagename is the source page
 $target is where the link should go
 $txt is the value to use for '$LinkText' in the output 
 $suffix is any suffix string to be added to $txt
 $fmt is a format string to use

If $txt is NULL or not specified, then it is automatically computed from $target.

If $fmt is NULL or not specified, then MakeLink uses the default format as specified by the type of link. For page links this means the $LinkPageExistsFmt and $LinkPageCreateFmt variables, for intermap-style links it comes from either the $IMapLinkFmt array or from $UrlLinkFmt. Inside of the formatting strings, $LinkUrl is replaced by the resolved url for the link, $LinkText is replaced with the appropriate text, and $LinkAlt is replaced by any "title" (alternate text) information associated with the link.

Also see: PmWiki:MakeLink and Cookbook:Functions#MakeLink

MakeUploadName($pagename, $x)

MakeUploadName?() simply takes a string $x (representing an attachment's name) and converts it to a valid name by removing any unwanted characters. It also requires the name to begin and end with an alphanumeric character, and as of 2.0.beta28 it forces any file extensions to lowercase. This function is defined in scripts/upload.php and only used when uploads are enabled.

SessionAuth($pagename, $auth=NULL)

SessionAuth?() manages keeping authentication via cookie-sessions. Session contains ever password or vaidated id and associated groups from previous calls.It adds elements passed by $auth to session. It also writes every element saved in session to $AuthPw(passwords) and $AuthList(ids and groups).

IsAuthorized($chal, $source, &$from)

IsAuthorized? takes a pageattributesstring (e. g. "id:user1 $1$Ff3w34HASH...") in $chal. $source is simply returned and used for building the authcascade (pageattributes - groupattributes - $DefaultPassword). $from will be returned if $chal is empty, because it is not checked before calling IsAuthorized?(), this is needed for the authcascade. IsAuthorized?() returns an array with three values: $auth 1 - authenticated, 0 - not authenticated, -1 - refused; $passwd; $source from the parameter list.

CondAuth ($pagename, 'auth level')

CondAuth implements the ConditionalMarkup for (:if auth level:). For instance CondAuth($pagename,'edit') is true if authorization level is 'edit'. Use inside local configuration files to build conditionals with a check of authorization level, similar to using (:if auth level:) on a wiki page.

Note that CondAuth() should be called after all authorization levels and passwords have been defined. For example, if you use it with Drafts, you should include the draft.php script before calling CondAuth():

   $EnableDrafts = 1;
   $DefaultPasswords['publish'] = crypt('secret');
   include_once("$FarmD/scripts/draft.php");
   if (! CondAuth($pagename, 'edit')) { /* whatever */ }

Best is to use CondAuth() near the bottom of your config.php script.

RetrieveAuthPage?($pagename, $level, $authprompt=true, $since=0)

Pm words as said in http://article.gmane.org/gmane.comp.web.wiki.pmwiki.user/12493/match=retrieveauthpage%% where:

   $pagename   - name of page to be read
   $level      - authorization level required (read/edit/auth/upload)
   $authprompt - true if user should be prompted for a password if needed
   $since      - how much of the page history to read
                 0 == read entire page including all of history
                 READPAGE_CURRENT == read page without loading history
                 timestamp == read history only back through timestamp

The $since parameter allows PmWiki to stop reading from a page file as soon as it has whatever information is needed -- i.e., if an operation such as browsing isn't going to need the page's history, then specifying READPAGE_CURRENT can result in a much faster loading time. (This can be especially important for things such as searching and page listings.)

Use e.g. $page = @RetrieveAuthPage('Main.MyPage', 'read') to obtain a page object that contains all the information of the correspondent file in separate keys, e.g. $page['text'] will contain a string with the current wiki markup of Main.MyPage?. Use this generally in preference to the alternative function ReadPage($pagename, $since=0) since it respects the authorisation of the user, i.e. it checks the authorisation level before loading the page, or it can be set to do so. ReadPage() reads a page regardless of permission.

Passing 'ALWAYS' as the authorization level (instead of 'read', 'edit', etc.) will cause RetrieveAuthPage? to always read and return the page, even if it happens to be protected by a read password.

RetrieveAuthSection?($pagename, $pagesection, $list=NULL, $auth='read')

RetrieveAuthSection? extracts a section of text from a page. If $pagesection starts with anything other than '#', it identifies the page to extract text from. Otherwise RetrieveAuthSection? looks in the pages given by $list, or in $pagename if $list is not specified.

  • The selected page is placed in the global $RASPageName variable.
  • The caller is responsible for calling Qualify() as needed.

Provides a way to limit the array that is returned by ReadPage?, so that it only pulls the content up to a specific section marker. For example, pulling from start of page to '##blogend':

function FeedText($pagename, &$page, $tag) {
  $text = RetrieveAuthSection($pagename, '##blogend');
  $content = MarkupToHTML($pagename, $text);
  return "<$tag><![CDATA[$content]]></$tag>";
}

The '##blogend' argument says to read from the beginning of the page to just before the line containing the marker. See IncludeOtherPages for more information about the section specifications.

This version won't read text from pages that are read-protected; if you want to get text even from read-protected pages, then

  $text = RetrieveAuthSection($pagename, '##blogend', NULL, 'ALWAYS');

UpdatePage($pagename, $old (page object), $new (page object));

More Technical Notes

UpdatePage() allows cookbook recipes to mimic the behavior of editing wiki pages via the browser. Internally, PmWiki does several house keeping tasks which are accessible via this function (preserving history/diff information, updating page revision numbers, updating RecentChanges pages, sending email notifications, etc._

  • "Page object" refers to an array pulled from ReadPage($pagename); Note that $new['text'] should contain all page data for the new version of the page.
  • If a page doesn't exist, UpdatePage() will attempt to create it.
  • Ignoring $old (e.g. UpdatePage($pagename, '', $new);) will erase all historical page data---a tabula rasa.

UpdatePage() cannot be called directly from config.php because there are necessary initializations which occur later in pmwiki.php. It is not enough to just load stdconfig.php. If you want to use UpdatePage() you will need to do it within a custom markup, a custom markup expression, or a custom action.

Categories: PmWiki Developer


PageFileFormat

You may have many documents that you would like to use a local program to format in a format PmWiki can display.

You could open each document and copy/paste the content to new pmwiki pages or you could format the document in advance and upload it using an FTP client.

Only two lines are necessary in a PmWiki page file:

version=pmwiki-2.1.0 urlencoded=1
text=Markup text

"version=" tells PmWiki that the values are urlencoded. The actual value doesn't matter, as long as "urlencoded=1" appears somewhere in the line.

"text=" needs to have the markup text with newlines converted to "%0a" and percent signs converted to "%25".

In addition, PmWiki writes pages with '<' encoded as "%3c" (to help with security), but it doesn't require that <'s be encoded that way in order to be able to read the page. More conversions are possible to be added in the future.

In order to let the (:pagelist :) markup work, make sure the filename begins with an uppercase letter.

In order to have the (:pagelist link= ... :) markup on other pages list this page, a third attribute is required:

targets=GroupName1.Pagename1,GroupName2.Pagename2,...

"targets=" is a comma delimited list of all links from the current page.


Keys you could see in a raw PmWiki file:

version
Version of PmWiki used to create the file More??? (ordered, urlencoded)
agent
Author's browser when saving the page
author
Last author to save page
charset
The character encoding of the page text, may be used by future upgrades
csum
Change summary
ctime
Page creation time
description
Page description. Used to fill <meta name='description' /> if set via(:description page'sdecription text:)
host
Host created this page
name
Name of the page (e.g., Main.WikiSandbox)
passwdattr
encrypted version of the password required to change attributes
passwdedit
encrypted version of the password required to edit
passwdread
encrypted version of the password required to read
passwdupload
encrypted version of the password required to upload
rev
Number of times the page has been edited
targets
Targets for links in the page
text
The page's wiki markup
time
Time the page was last saved (seconds since 1 Jan 1970 00:00 UTC)
title
Page title set via (:title The Page Title:).
newline
Character used for newlines (deprecated)
updatedto
The version to which PmWiki has been updated to by upgrades.php (only on SiteAdmin.Status)

Below these you will see information used to keep track of the page's revision history.

Creating a Page for Distribution

A simple way to create a wikipage file to use for distribution (for example with a recipe or a skin) is to create the page with PmWiki and then use a text editor to delete all lines but version, text, and ctime. Example:

version=pmwiki-2.1.0 ordered=1 urlencoded=1
text=This is a line.%0aThis is another.
ctime=1142030000

Keeping track of page history

Inside of a page file, PmWiki stores the latest version of the markup text, and uses this to render the page. The page history is kept as a sequence of differences between the latest version of the page and each previous version.

PmWiki normally puts the page history at the end of each page file in reverse chronological sequence, and sets the "ordered=1" items in the header. If an operation needs only the most recent version of a page, then PmWiki will stop reading and processing a page file at the point where the history begins, potentially saving a lot of time and memory. If the "ordered=1" flag isn't present, PmWiki makes no assumptions about the ordering of items in the pagefile and processes the entire file.

Load pages from text files

See Cookbook: Import text. Import text files as PmWiki pages

Unix utility to extract wiki text

The following unix script (tested on MacOSX?) will extract and decode the current text from a wiki file:

#!/bin/tcsh
# wtext - extract wiki text
#
# wtext wikifile > output

set fn = "$1"
if ("$fn" == "") then
  echo "need input file parameter"
  exit 999
endif
if (! -f $fn) then
  echo "$fn does not exist"
  exit 999
endif
rm sedin.$$ >& /dev/null
set ch = `grep ^newline= $fn | cut -d= -f2`
if ("$ch" == "") set ch = "%0a"
cat <<eof > sedin.$$
s/^text=//
s/$ch/\
/g
s/%3c/</g
s/%25/%/g
eof
grep "^text=" "$1" | sed -f sedin.$$
rm sedin.$$ >& /dev/null

See also

Categories: PmWiki Developer


Audiences

This page contains Patrick Michaud's comments regarding the "audiences" for which PmWiki was designed. As such, many people are reluctant to modify the page, because it is a statement of his opinions and describes some of the thought that went into creating PmWiki. (And we all thank him for that!)

Patrick's comments

I think of PmWiki in terms of two audiences:

  • Authors are the people who generate web content using PmWiki, and
  • wiki administrators are the folks who install, configure, and maintain a PmWiki installation on a web server.

In some senses it could be claimed that as the primary developer of PmWiki I should only have wiki administrators as my target audience, and that authors are the target audience for the administrators. But what really makes PmWiki useful to wiki administrators is that I've put a lot of consideration into creating a tool that is usable by authors, so I have to keep the needs of both audiences in mind as I'm designing and adding new features to PmWiki.

Within the authoring audience I see that there are "naive authors" and "experienced authors".

"Naive authors" are the folks who use wiki to generate content but may know next-to-nothing about HTML, much less style sheets or PHP or the like. Naive authors are easily discouraged from generating web content if they have to wade through markup text that has lots of funny and cryptic symbols in them. So, if we want a site with lots of contributors, we have to be very careful not to do things that will cause this group to exclude themselves from participating.

"Experienced authors" are the folks who know a lot about HTML and could write their content as HTML, but have chosen to use wiki because of its other useful features (ease of linking, collaboration, ease of updates, revision histories, etc.) or because they want to collaborate with naive authors. Experienced authors usually don't have any problem with documents with lots of ugly markup in them; after all, they already know HTML. Experienced authors are sometimes frustrated with wiki because it doesn't have markup that would let them do something they know they can do in HTML (e.g., tables, stylesheets, colored text, etc.). And, they sometimes have difficulty understanding why naive authors would turn away from documents that have lots of markup sequences in them.

For the wiki administrator audience--the folks who install and may want to customize PmWiki--their backgrounds and goals are often quite diverse. PmWiki is designed so that it can be installed and be useful with minimal HTML/PHP knowledge, but it doesn't restrict people who know HTML/PHP from doing some fairly complex things. For one, PmWiki allows a site administrator to build-in markup sequences and features customized to his/her needs (and the needs of his/her audiences).

The separate needs of these audiences are behind most of the PmWikiPhilosophies. The people who develop PmWiki software must continually keep naive authors in mind as new features are requested and proposed by expert authors and Wiki Administrators. Sometimes it may seem to these latter groups that it's okay to implement the complex features because "naive authors don't have to use them", but the truth is that if complex/ugly markup sequences are available then they will eventually be used by someone, and once used they become a barrier to the naive authors. So, if I see that a feature could become a barrier to a naive author I don't include it in the base implementation of PmWiki, but instead find ways to let Wiki Administrators include it as a local customization.


Contributors

Here's a list of contributors to PmWiki development and improvement. My apologies if I've forgotten anyone -- feel free to add your name if you've been left out, feel free to remove your name if you don't want to be associated with these people. :-)

  • GNUZoo? - Several recipes, some security and bug fixes
  • Scott Duff - pmwe, simple-journal.php, all-around Pm sanity checker
  • Ross Kowalski - uploads and printable page research
  • John Rankin - WikiTrails, Links, EditQuickReference, notify.php, documentation, debugging
  • Joachim Durchholz - hacking documentation, general pest
  • Jessica Tishmack - uploads, testing
  • Jean-Claude Gorichon - voting
  • Janice Heinold - early PmWiki testing and suggestions, documentation
  • James Davis - WikiStyles markup, testing
  • Isabelle Michaud - floating images markup, Wiki Groups, uploads/attachments
  • Glenn Blalock - WikiStyles suggestions, testing, documentation
  • Dawn Green - WikiStyles suggestions, uploads, documentation
  • Christian Ridderström - pmwiki-mode for Emacs and some other hacks/modifications.
  • Carlo Strozzi - Internationalization, PmWiki on Boa, HTML redirection
  • Michael Weiner - Modifications to the ToDo?, RssFeedDisplay?, MyPmWiki?, and CommentBox? recipes
  • Criss Ittermann (aka Crisses/XES) - ye old best seller Blocklist2 that topped the charts for a while and many other recipes
  • Rev. Dr. Ian MacGregor? - I've contributed with monetary donations, skins, bug reports and continued testing. My home page is powered by PmWiki.
  • Petko Yotov - I have been the PmWiki core developer and pmwiki.org webmaster since January 2009 (after having worked with it since 2004). My contributions are at the Change log page, in the PITS issue tracking system and in the mailing lists. My cookbook recipes can be found at my profile page.

MailingLists

There are several mailing lists available for PmWiki.

[ pmwiki-users ]
This is a great resource where a very helpful group of people will answer questions and discuss PmWiki development. Traffic is around 20-40 messages a day (on slow days).
If you ask a question on the list and it doesn't get answered, don't feel let down. Just ask it again. It probably slipped by unnoticed.
[ pmwiki-users-de ]
A mailing list for german-speaking users of PmWiki. Archived at
[ pmwiki-users-es ]
Lista de usuarios PmWiki en Español.
[ pmwiki-users-fr ]
A mailing list for french-speaking users of PmWiki.
[ pmwiki-devel ]
This list was created to lower the traffic on pmwiki-users, it focuses on discussions surrounding code development for PmWiki (both core and recipe development).
[ pmwiki-announce ]
Announcements of new version releases and urgent information. If you use PmWiki in a production environment, this low-volume list is highly recommended. The archive is at:

Suggestions:

  • If you reply to a digest message, please remove the messages irrelevant to your reply before sending it back to the list.
    • It's also helpful (but less important) to change "Re: pmwiki-users Digest, Vol [...]" to "Re: [the original subject]" because some mail programs determine threads based on the subject.
  • If you address a reply to a single list member, please take the [pmwiki-users] off the subject line, or it's possible for your message to get lost in the mailing list traffic. Many people filter list traffic to a separate mailbox.

Changing mail list settings

Here are some tips regarding changing the mailing list settings:

  • Logging in...
    • First go to http://pmichaud.com/mailman/listinfo/pmwiki-users and enter your e-mail address in the field at the bottom of the page, to the left of the button Unsubscribe or edit options.
    • Next you need to enter your password. As you've probably forgotten this, use the button Remind at the bottom of the page to get a new password.
    • Finally enter the password you should get momentarily via e-mail.
  • You can directly go to the options web page through a URI such as the following:
http://host.pmichaud.com/mailman/options/pmwiki-users/<user>%40<domain>
where <user> is everything before the @ in an e-mail address, and <domain> is everything after ( For those who wonder, the %40 in the URI just stands for '@'.
  • You can also obtain various help by sending an email to pmwiki-users-request [snail] pmichaud [period] com with the text help in either the subject or the body.

Newsgroups (NNTP)

You may be interested, that the lists are also accessible as newsgroups.

The NNTP server is:

  • news.gmane.org [9]

The groups are:

  • gmane.comp.web.wiki.pmwiki.user
  • gmane.comp.web.wiki.pmwiki.announce
  • gmane.comp.web.wiki.pmwiki.user.de

PmWikiPhilosophy

This page describes some of the ideas that guide the design and implementation of PmWiki. Patrick Michaud doesn't claim that anything listed below is an original idea; these are just what drive the development of PmWiki. You're welcome to express your disagreement with anything listed below. PmWiki.Audiences also describes much of the reasoning behind the ideas given below.

1. Favor writers over readers
At its heart, PmWiki is a collaborative authoring system for hyperlinked documents. It's hard enough to get people (including Pm) to contribute written material; making authors deal with HTML markup and linking issues places more obstacles to active contribution. So, PmWiki aims to make it easier to author documents, even if doing so limits the types of documents being authored.

2. Don't try to replace HTML
PmWiki doesn't make any attempt to do everything that can be done in HTML. There are good reasons that people don't use web browsers to edit HTML--it's just not very effective. If you need to be writing lots of funky HTML in a web page, then PmWiki is not what you should be using to create it. What PmWiki does try to do is make it easy to link PmWiki to other "non-wiki" web documents, to embed PmWiki pages inside of complex web pages, and to allow other web documents to easily link to PmWiki.
This principle also follows from the "favor writers over readers" principle above--every new feature added to PmWiki requires some sort of additional markup to support it. Pretty soon the source document looks pretty ugly and we'd all be better off just writing HTML.
Another reason for avoiding arbitrary HTML is that ill-formed HTML can cause pages to stop displaying completely, and arbitrary HTML can be a security risk--more so when pages can be created anonymously. See http://www.cert.org/advisories/CA-2000-02.html for more information.

3. Avoid gratuitous features (or "creeping featurism")
In general PmWiki features are implemented in response to specific needs, rather than because someone identifies something that "might be useful". In any sort of useful system, it's hard to change a poorly designed feature once people have built a lot of structure based on it. (Need an example? Look at MS-DOS or Windows.) One way to avoid poor design is to resist the temptation to implement something until you have a clearer idea of how it will be used.

4. Support collaborative maintenance of public web pages
Although this wasn't at all the original intent of PmWiki, it became quickly obvious that WikiWikiWeb principles could be used to make it easier for groups to collaboratively design and maintain a public web site presence. PmWiki allows individual pages to be password protected, and a couple of local customizations makes it easy to protect large sections of PmWiki pages. Furthermore, in many ways PmWiki provides "style sheets on steroids": you can quickly change the headers, footers, and other elements on a large group of pages without ever having to touch the individual page contents. Finally, it's relatively easy to add custom markup for specialized applications.

5. Be easy to install, configure, and maintain
With a gzip-compressed file size of just around 400K, uploading PmWiki to your server is a speedy operation. Do a chmod or two, update a few settings in config.php and you should be up and running. PmWiki stores all data in flat files, so there is no need for MySQL or other utilities. Upgrading is usually a simple matter of copying the latest version's files over the files of your existing PmWiki installation. (One of the biggest reasons for the creation of PmWiki was that other wiki engines at the time required modifications to the distribution files, so admins ended up losing their customizations on every upgrade.)

DesignNotes

Here are some of the features and notes about PmWiki's design decisions. Many of these derive directly from the PmWiki Philosophy and lots of discussion on the mailing lists.

Why doesn't PmWiki use hierarchical / nested groups?

It essentially comes down to figuring out how to handle page links between nested groups; if someone can figure out an obvious, intuitive way for authors to do that, then nested groups become plausible. See Design Notes and PmWiki:Hierarchical Groups.

Why don't PmWiki's scripts have a closing ?> tag?

All of PmWiki's scripts now omit the closing ?> tag. The tag is not required, and it avoids problems with unnoticed spaces or blank lines at the end of the file. Also, some file transfer protocols may change the newline character(s) in the file, which can also cause problems. See also the Instruction separation page in the PHP manual.

Does PmWiki support WYSIWYG editing (or something like the FCKEditor?)?

Short answer: PmWiki provides GUI buttons in a toolbar for common markups, but otherwise does not have WYSIWYG editing. For the reasons why, see PmWiki:WYSIWYG.

Categories: PmWiki Developer


Release Notes

See also: Change log and Road map.

Version 2.2.44 (2012-10-21)

This version improves the display of consecutive whitespaces in page histories, and fixes the definition of PageTextVariables containing a dash. The documentation was updated.

Version 2.2.43 (2012-09-20)

This version makes it possible to use HTML attribute names to contain dashes, and removes a warning when editing and previewing Site.EditForm. The documentation was updated.

Version 2.2.42 (2012-08-20)

This version provides a workaround for cases when a wiki page contains a character nonexistent in the active encoding. The documentation was updated.

Version 2.2.41 (2012-08-12)

This version changes the internal $KeepToken separator to be compatible with more encodings. The documentation was updated.

Version 2.2.40 (2012-07-21)

This version provides a helper function replacing htmlspecialchars() and compatible with PHP 5.4. The documentation was updated.

Version 2.2.39 (2012-06-25)

This version provides a fix for links to attachments containing international characters. The documentation was updated.

Version 2.2.38 (2012-05-21)

This version fixes a "parameter count" warning which appeared on some websites.

Version 2.2.37 (2012-05-01)

This version provides a workaround for installations with broken iconv() function, while optimizing the recode function. This should fix the "Unable to retrieve edit form" problem in some wikis. Dots in sections are now better supported, PageVariables are expanded in PageList? template defaults, and the documentation is updated.

Version 2.2.36 (2011-12-28)

This version fixes the recode function to try to recover Windows-1252 characters in ISO-8859-1 files. A new variable $EnableOldCharset enables the $page["=oldcharset"] entry which will be used in the future. A couple of minor bugs were fixed and the documentation was updated.

Version 2.2.35 (2011-11-11)

This release fixes a critical PHP injection vulnerability, reported today by Egidio Romano. PmWiki versions 2.2.X, 2.1.X, 2.0.X and 2.0.beta33 and newer are vulnerable. When you upgrade, please read carefully the Release notes for all PmWiki versions since yours.

If you cannot upgrade, it is recommended to disable Searches at the earliest opportunity (even if your wiki skin doesn't have a search form). Add to config.php such a line:

  if ($action == 'search') $action = 'browse';

If your old version wiki allows editing by not entirely trusted visitors, even on limited pages like a WikiSandbox, you should also disable PageLists. Add to config.php this line:

  $EnablePageList = 0;

This version has an important change for international wikis: the XLPage?() function no longer loads encoding scripts such as xlpage-utf-8.php. When you upgrade, you need to include those scripts from config.php, before calling XLPage?():

  include_once("scripts/xlpage-utf-8.php"); # if your wiki uses UTF-8
  XLPage?('bg','PmWikiBg.XLPage');

All links can now have tooltip titles. Previously, only images and external links could have tooltip titles, now this feature is enabled for internal links. To set a tooltip title, add it in quotes after the link address:

  [[Main.HomePage"This is a tooltip title"]]
  [[Main.HomePage"This is a tooltip title"|Home]]
  [[http://www.pmwiki.org"Home of PmWiki"]]
  Attach:image.jpg"Tooltip title of the image"

The following new upload extensions were added: svg, xcf, ogg, flac, ogv, mp4, webm, odg, epub. A couple of minor optimizations were added (MarkupExpressions and rendering of page history) and the documentation was updated.

Version 2.2.34 (2011-10-10)

This version resets the timestamps of the default pages Site(Admin).AuthUser which are expected in case of upgrades from the versions 2.1.*. Core MarkupExpressions which manipulate strings should now work better with international characters. The documentation was updated to its latest state from pmwiki.org.

Version 2.2.33 (2011-09-23)

This version fixes a security bug introduced in 2.2.32 which left the groups Site and SiteAdmin? open for reading and editing because the pages Site.GroupAttributes and SiteAdmin.GroupAttributes didn't have all necessary attributes.

All wikis running 2.2.32 should upgrade. If you cannot immediately upgrade, you can set the attributes from your wiki:

  • open the attributes page [[SiteAdmin.GroupAttributes?action=attr]] and set a "read" and an "edit" password, @lock is recommended.
  • open the attributes page [[Site.GroupAttributes?action=attr]] and set an "edit" password, @lock is recommended. Do not set a "read" password here.

The release also fixes the refcount.php script to produce valid HTML, and updates intermap.txt entries PITS: and Wikipedia: to point to their current locations.

Version 2.2.32 (2011-09-18)

This is the first version shipping with the core documentation in the UTF-8 encoding. PmWiki will automatically convert it on the fly for wikis using an older encoding.

It is recommended that all new PmWiki installations enable UTF-8. Migration of existing wikis from an older encoding to UTF-8 shouldn't be rushed: it is not trivial and will be documented in the future.

A required HTML xmlns attribute was added to the print skin template. The history rendering is now faster when many lines are added or removed.

Note: Due to a manipulation error, a version 2.2.31 was created before it was ready for a release.

Version 2.2.30 (2011-08-13)

This version fixes a $Charset definition in international iso-8859-*.php files. This will help for a future transition to UTF-8.

A variable $EnableRangeMatchUTF8 was added, set it to 1 to enable range matches of pagenames in UTF-8 like [A-D]. Previously the range matches were always enabled in UTF-8, but we found out that on some installations this feature breaks all pagelists, even those without range matches. In case the feature worked for you, you can re-enable it.

Version 2.2.29 (2011-07-24)

This release fixes Attach links that were broken with the Path fix in 2.2.28 earlier today.

Version 2.2.28 (2011-07-24)

This release fixes 2 potential XSS vulnerabilities and a bug with Path: links.

Version 2.2.27 (2011-06-19)

This release fixes a validation bug on pages after a redirection. A new block WikiStyle %justify% was added, allowing left and right aligned text. The page history now accepts a URL parameter ?nodiff=1 which hides the rendering of edit differences, showing only timestamps, authors, summaries and "Restore" links; it allows to restore a vandalized page with a huge contents or history which otherwise would break the memory or time limits of the server.

Version 2.2.26 (2011-05-21)

This release fixes a redundant removal of link hashes from WikiTrails, and updates the documentation to the most recent version from PmWiki.org.

Version 2.2.25 (2011-03-22)

This release only updates the documentation to the latest state on pmwiki.org.

Version 2.2.24 (2011-02-15)

This version reverts the way existing PageVariables are processed, like version 2.2.21 or earlier, but it adds a special variable $authpage which can be used in PageVar? definitions. It is the same as the $page array, but exists only if the visitor has read permissions. For example, an administrator can set to config.php:

  $FmtPV['$LastModifiedSummary'] = '@$authpage["csum"]'; # instead of '@$page["csum"]'

Then, the edit summary metadata will only be available if the user has read permissions.

Version 2.2.23 (2011-01-25)

This version sets the default value of $EnablePageVarAuth to 0 until we investigate a reported problem with authentication.

Version 2.2.22 (2011-01-16)

This version adds the variable $EnableXLPageScriptLoad which, if set to 0, will prevent authors to load scripts from XLPage? and to accidentally change the encoding of the wiki. If you use it, make sure you include the required files, eg. xlpage-utf-8.php from local config files.

PageVariables should now respect authentications: without read permissions, the title, description, change summary, author of a protected page are unavailable. PageVariables that are computed without reading the page are still available (eg. $Group, $Namespaced, $Version etc.). Administrators can revert the previous behavior by adding to config.php such a line:

$EnablePageVarAuth = 0;

Version 2.2.21 (2010-12-14)

Due to a mis-configuration of a local svn repository, some of the changes intended for 2.2.20 didn't make it in the correct branch. This release corrects this.

Version 2.2.20 (2010-12-14)

This version fixes a potential XSS vulnerability, reported today. An AuthUser bug with excluding users from authgroups was fixed. A new InterMap prefix PmL10n?: was added, it leads to the Localization section on PmWiki.org and should help the work of translators. A couple of other minor bugs were fixed and the documentation was updated.

Version 2.2.19 (2010-11-10)

This is a documentation-update release.

Version 2.2.18 (2010-09-04)

This version fixes 3 minor bugs, and updates the documentation.

Version 2.2.17 (2010-06-20)

This version adds a variable $PostConfig containing functions and scripts to be loaded after stdconfig.php. Tabindex was added as a valid form field attribute. Protected downloads now respect existing browser caches. AuthUser now allows more flexible cookbook recipe integration. A couple of bugs were fixed and the documentation was updated.

Version 2.2.16 (2010-05-10)

This version fixes a bug with parsing html attributes which could allow XSS injection. Wikis allowing unprotected editing are encouraged to upgrade.

A bug with the "center" button of the GUI edit toolbar was corrected.

The "exists" conditional now accepts wildcards, for example:

  (:if exists Main.*:)There are pages in the Main group (:if:)

The documentation was updated.

Version 2.2.15 (2010-03-27)

This version adds some minor bugfixes and optimizations notably a bug with (:template none:) introduced in the last version 2.2.14.

Version 2.2.14 (2010-02-27)

This release corrects inline styles for WikiTrail links. Undefined include/template {$$variables} are now removed from the included section, like Page(Text)Variables, and can be used in conditional expressions. If needed, this change can be reverted by adding to config.php such a line:

  $EnableUndefinedTemplateVars = 1; # keep and display unset {$$variables}

PageList? templates now accept the sections !first and !last for markup to appear for every page in list except the first or last one.

"Title" attributes were added to external links. You can have tooltip titles on external links, including InterMap and attachments, by adding the link title in double quotes after the URL:

  [[http://www.pmwiki.org"Home of PmWiki"| External link]]

For international wikis, PmWiki now automatically translates the titles of technical pages like GroupAttributes or RecentChanges -- just define these strings as usual in XLPage?, for example, in French:

  'AllRecentChanges?' => 'Tous les changements récents',

Some minor optimizations were done and the documentation was updated.

Version 2.2.13 (2010-02-21)

This release fixes a bug with $DiffKeepNum introduced in 2.2.10 -- the count of revisions was incorrect and a page could drop more revisions than it should.

The page history layout was modified with a rough consensus in the community. The history now defaults to "source" view with word-level highlighting of the differences. Authors can see the changes in rendered output by clicking on the link "Show changes to output". Admins can switch back the default by adding such a line to config.php:

  $DiffShow['source'] = (@$_REQUEST['source']=='y')?'y':'n';

To disable word-level highlighting and show plain text changes:

  $EnableDiffInline = 0;

In the page history rendering, a few minor bugs were fixed and the code was slightly optimized.

The documentation was updated.

Version 2.2.12 (2010-02-17)

This release adds simple word-level highlighting of differences in the page history, when "Show changes to markup" is selected. To enable the feature, add to config.php such a line:

  $EnableDiffInline = 1;

This feature is like what the InlineDiff? recipe provides, but not exactly the same, and the implementation is simpler. It is enabled on PmWiki.org and can be improved -- your comments are welcome.

Version 2.2.11 (2010-02-14)

This release adds two new table directives for header cells, (:head:) and (:headnr:). They work the same way as (:cell:) and (:cellnr:) except that create <th> instead of <td> html tags.

The pagerev.php script was refactored into separate functions to allow easier integration of recipes displaying the page history.

A couple of minor bugs were fixed and the documentation was updated.

Version 2.2.9, 2.2.10 (2010-01-17)

Most important in this release is the official change of $EnableRelativePageVars to 1. The change is about how {$Variable} in included pages is understood by PmWiki.

  • When $EnableRelativePageVars is set to 0, {$Name} displays the name of the currently browsed page. Even if {$Name} is in an included page, it will display the name of the browsed page.
  • When $EnableRelativePageVars is set to 1, {$Name} displays the name of the physical page where it written. If {$Name} is in an included page, it will display the name of the included page.
  • {*$Name} always displays the name of the currently browsed page, regardless of $EnableRelativePageVars.

So, if your wiki relies on page variables from included pages, and doesn't have $EnableRelativePageVars set to 1, after upgrading to 2.2.9, you can revert to the previous behavior by adding to config.php such a line:

  $EnableRelativePageVars = 0;

More information about page variables can be found at:

  http://www.pmwiki.org/wiki/PmWiki/PageVariables

This release adds a new variable $EnablePageTitlePriority which defines how to treat multiple (:title..:) directives. If set to 1, the first title directive will be used, and if a page defines a title, directives from included pages cannot override it. PmWiki default is 0, for years, the last title directive was used (it could come from an included page or GroupFooter).

This release also adds a new variable $DiffKeepNum, specifying the minimum number (default 20) of edits that will be kept even if some of them are older than the limit of $DiffKeepDays.

A number of bugs were fixed and the documentation was updated.

Version 2.2.8 (2009-12-07)

This release fixes another PHP 5.3 compatibility issue with conditional markup. The Author field now handles apostrophes correctly. The documentation was updated.

Version 2.2.7 (2009-11-08)

This release fixes most PHP 5.3 compatibility issues. Unfortunately some specific builds for Windows may still have problems, which are unrelated to PmWiki. Notably, on Windows, all passwords need to be 4 characters or longer.

Upload names with spaces are now correctly quoted. The documentation was updated.

Version 2.2.6 (2009-10-04)

With this release it is now possible to display recently uploaded files to the RecentChanges pages -- if you have been using the RecentUploadsLog? recipe, please uninstall it and follow the instructions at http://www.pmwiki.org/wiki/Cookbook/RecentUploadsLog.

The release also introduces $MakeUploadNamePatterns to allow custom filename normalization for attachements. It is now possible to replace $PageListFilters and $FPLTemplateFunctions with custom functions. Notify should now work in safe_mode. Some bugs were fixed, among which one with conditional markup with dates. The documentation was updated.

Version 2.2.5 (2009-08-25)

This release adds a new markup for Pagelist templates, (:template none:) which allows a message to be set when the search found no pages. The FPLTemplate() function was broken into configurable sub-parts to allow development hooks. A number of bugs were fixed, and the documentation was updated.

Version 2.2.4 (2009-07-16)

This release fixes a bug introduced earlier today with HTML entities in XLPages?.

Version 2.2.3 (2009-07-16)

This release fixes six potential XSS vulnerabilities, reported by Michael Engelke. The vulnerabilities may affect wikis open for editing and may allow the injection of external JavaScripts? in their pages. Public open wikis should upgrade.

A new variable $EnableUploadGroupAuth was added; if set to 1, it allows password-protected uploads to be checked against the Group password.

It is now possible to use @_site_edit, @_site_read, @_site_admin or @_site_upload global passwords in GroupAttributes pages.

A number of other small bugs were fixed, and the documentation was updated.

Version 2.2.2 (2009-06-21)

The major news in this release is a fix of an AuthUser vulnerability.

The vulnerability affects only wikis that (1) rely on the AuthUser core module for User:Password authentication, -AND- (2) where the PHP installation runs with the variable "magic_quotes_gpc" disabled.

All PmWiki 2.1.x versions from pmwiki-2.1.beta6 on, all 2.2.betaX, 2.2.0, and 2.2.1 are affected.

The PmWiki SiteAnalyzer can detect if your wiki needs to upgrade:

  http://www.pmwiki.org/wiki/PmWiki/SiteAnalyzer

If your wiki is vulnerable, you should do one of the following at the earliest opportunity:

  • Upgrade to a version of PmWiki at least 2.2.2 or greater.
  • Turn on magic_quotes_gpc in the php.ini file or in a .htaccess file.

Alternatively, you can temporarily disable AuthUser until you upgrade.

Note that even if your wiki does not have the AuthUser vulnerability at the moment, you are strongly encouraged to upgrade to PmWiki version 2.2.2 or later, as some future configuration of your hosting server might put you at risk.

This release also comes with minor updates in the local documentation; fixes were applied for international wikis - notably global variables in xlpage-utf-8.php and a new variable $EnableNotifySubjectEncode, which allows e-mail clients to correctly display the Subject header; and a number of other small bugs were fixed.

Version 2.2.1 (2009-03-28)

This release comes with an updated local documentation; wiki trails now work cross-group; guiedit.php now produces valid HTML, and other small bugs were fixed. We also added $EnableRedirectQuiet, which allows redirects to take place without any mention of "redirected from page ....".

Version 2.2.0 (2009-01-18)

This is a summary of changes from 2.1.x to 2.2.0.

  • Several pages that were formerly in the Site.* group are now in a separate SiteAdmin?.* group, which is read-restricted by default. The affected pages include Site.AuthUser, Site.AuthList, Site.NotifyList, Site.Blocklist, and Site.ApprovedUrls . If upgrading from an earlier version of PmWiki, PmWiki will prompt to automatically copy these pages to their new location if needed. If a site wishes to continue using the old Site.* group for these pages, simply set
when carrying out this upgrade inspect your config files for lines such as
$BlocklistDownload['Site.Blocklist-PmWiki'] = array('format' => 'pmwiki');
as you may wish to fix then, eg
$BlocklistDownload[$SiteAdminGroup . '.Blocklist-PmWiki'] = array('format' => 'pmwiki');
  • Important Change in Passwords in PmWiki 2.2 indicating that the group can be edited even if a site password is set will be done by "@nopass" prior it was done by "nopass"
When migrating a wiki you will have to manually modify the permission or by a script replace in all the page concerned passwdread=nopass: by passwdread=@nopass (see PITS:00961) --isidor
  • It's now easy to disable the rule that causes lines with leading spaces to be treated as preformatted text -- simply set $EnableWSPre=0; to disable this rule.
    Important: There is ongoing discussion that the leading whitespace rule may be disabled by default in a future versions of PmWiki. If you want to make sure that the rule will continue to work in future upgrades, set $EnableWSPre=1; in local/config.php.
  • The $ROSPatterns variable has changed somewhat -- replacement strings are no longer automatically passed through FmtPageName() prior to substitution (i.e., it must now be done explicitly).
  • Page variables and page links inside of (:include:) pages are now treated as relative to the included page, instead of the currently browsed page. In short, the idea is that links and page variables should be evaluated with respect to the page in which they are written, as opposed to the page in which they appear. This seems to be more in line with what authors expect. There are a number of important ramifications of this change:

  • We now have a new {*$var} form of page variable, which always refers to "the currently displayed page". Pages such as Site.PageActions and Site.EditForm that are designed to work on "the currently browsed page" should generally switch to using {*$FullName} instead of {$FullName}.
  • The $EnableRelativePageLinks and $EnableRelativePageVars settings control the treatment of links and page variables in included pages. However, to minimize disruption to existing sites, $EnableRelativePageVars defaults to disabled. This will give existing sites an opportunity to convert any absolute {$var} references to be {*$var} instead.
  • Eventually $EnableRelativePageVars will be enabled by default, so we highly recommend setting $EnableRelativePageVars = 1; in local/config.php to see how a site will react to the new interpretation. Administrators should especially check any customized versions of the following:
    SideBar pages with ?action= links for the current page
    Page lists that refer to the current group or page, etc in sidebars, headers, and footers
  • The (:include:) directive now has a basepage= option whereby an author can explicitly specify the page upon which relative links and page variables should be based. If no basepage= option is specified, the included page is assumed to be the base.
  • Sites that want to retain the pre-2.2 behavior of (:include:) and other items can set $Transition['version'] = 2001900; to automatically retain the 2.1.x defaults.
  • Text inserted via (:include:) can contain "immediate substitutions" of the form {$$option} -- these are substituted with the value of any options provided to the include directive.
  • PmWiki now recognizes when it is being accessed via "https:" and switches its internal links appropriately. This can be overridden by explicitly setting $ScriptUrl and $PubDirUrl.
  • A new $EnableLinkPageRelative option allows PmWiki to generate relative urls for page links instead of absolute urls.
  • Draft handling capabilities have been greatly improved. When $EnableDrafts is set, then the "Save" button is relabeled to "Publish" and a "Save draft" button appears. In addition, an $EnablePublishAttr configuration variable adds a new "publish" authorization level to distinguish editing from publishing. See PmWiki:Drafts for more details.

  • There is a new {$:var} "page text variable" available that is able to grab text excerpts out of markup content. For example, {SomePage$:Xyz} will be replaced by a definition of "Xyz" in SomePage. Page text variables can be defined using definition markup, a line beginning with the variable name and a colon, or a special directive form (that doesn't display anything on output):
    :Xyz: some value            # definition list form
    Xyz: some value             # colon form
    (:Xyz: some value:)         # directive form
    

  • The (:pagelist:) command can now filter pages based on the contents of page variables and/or page text variables. For example, the following directive displays only those pages that have an "Xyz" page text variable with "some value":
    (:pagelist $:Xyz="some value":)
    Wildcards also work here, thus the following pagelist command lists pages where the page's title starts with the letter "a":
    (:pagelist $Title=A* :)
  • The if= option to (:pagelist) can be used to filter pages based on conditional markup:
    (:pagelist if="auth upload {=$FullName}":) pages with upload permission
    (:pagelist if="date today.. {=$Name}":) pages with names that are dates later than today
  • Spaces no longer separate wildcard patterns -- use commas. (Most people have been doing this already.)
  • Because page variables are now "relative", the {$PageCount}, {$GroupCount}, {$GroupPageCount} variables used in pagelist templates are now {$$PageCount}, {$$GroupCount}, {$$GroupPageCount}.
  • One can now use {$$option} in a pagelist template to obtain the value of any 'option=' provided to the (:pagelist:) command.
  • The (:pagelist:) directive no longer accepts parameters from urls or forms by default. In order to have it accept such parameters (which was the default in 2.1 and earlier), add a request=1 option to the (:pagelist:) directive.
  • The count= option to pagelists now accepts negative values to count from the end of the list. Thus count=5 returns the the first five pages in the list, and count=-5 returns the last five pages in the list. In addition, ranges of pages may be specified, as in count=10..19 or count=-10..-5.
  • Pagelist templates may have special (:template first ...:) and (:template last ...:) sections to specify output for the first or last page in the list or a group. There's also a (:template defaults ...:) to allow a template to specify default options.
  • PmWiki comes with an ability to cache the results of certain (:pagelist:) directives, to speed up processing on subsequent visits to the page. To enable this feature, set $PageListCacheDir to the name of a writable directory (e.g., work.d/).
  • The (:if ...:) conditional markup now also understands (:elseif ...:) and (:else:). In addition, markup can nest conditionals by placing digits after if/elseif/else, as in (:if1 ...), (:elseif1 ...:), (:else1:), etc.
  • The (:if date ...:) conditional markup can now perform date comparisons for dates other than the current date and time.
  • WikiTrails can now specify #anchor identifiers to use only sections of pages as a trail.
  • A new (:if ontrail ...:) condition allows testing if a page is listed on a trail.
  • The extensions .odt, .ods, and .odp (from OpenOffice?.org) are now recognized as valid attachment types by default.
  • A new blocklist capability has been added to the core distribution. It allows blocking of posts based on IP address, phrase, or regular expression, and can also make use of publicly available standard blocklists. See PmWiki.Blocklist for details.
  • There is a new SiteAdmin.AuthList page that can display a summary of all password and permissions settings for pages on a site. This page is restricted to administrators by default.
  • There are new {$PasswdRead}, {$PasswdEdit}, etc. variables that display the current password settings for a page (assuming the browser has attr permissions or whatever permissions are set in $PasswdVarAuth).
  • Forms creation via the (:input:) markup has been internally refactored somewhat (and may still undergo some changes prior to 2.2.0 release). The new (:input select ...:) markup can be used to create select boxes, and (:input default ...:) can be used to set default control values, including for radio buttons and checkboxes.
  • The (:input textarea:) markup now can take values from other sources, including page text variables from other pages.
  • Specifying focus=1 on an (:input:) control causes that control to receive the input focus when a page is loaded. If a page has multiple controls requesting the focus, then the first control with the lowest value of focus= "wins".
  • PmWiki now provides a scripts/creole.php module to enable Creole standard markup. To enable this, add include_once('scripts/creole.php') to a local customization file.
  • PmWiki adds a new {(...)} markup expression capability, which allows various simple string and data processing (e.g., formatting of dates and times). This is extensible so that recipe authors and system administrators can easily add custom expression operators.
  • It's now possible to configure PmWiki to automatically create Category pages whenever a page is saved with category links and the corresponding category doesn't already exist. Pages are created only if the author has appropriate write permissions into the group. To enable this behavior, add the following to local/config.php:
    $AutoCreate['/^Category\\./'] = array('ctime' => $Now);
  • Sites with wikiwords enabled can now set $WikiWordCount['WikiWord'] to -1 to indicate that 'WikiWord' should not be spaced according to $SpaceWikiWords.
  • WikiWords that follow # or & are no longer treated as WikiWords.
  • Links to non-existent group home pages (e.g., [[Group.]] and [[Group/]]) will now go to the first valid entry of $PagePathFmt, instead of being hardcoded to "Group.Group". For example, to set PmWiki to default group home pages to $DefaultName, use
    $PagePathFmt = array('{$Group}.$1', '$1.{$DefaultName}', '$1.$1');
  • PmWiki now provides a $CurrentTimeISO and $TimeISOFmt variables, for specifying dates in ISO format.
  • Cookbook authors can use the internal PmWiki function UpdatePage (temporarily documented at DebuggingForCookbookAuthors) to change page text while preserving history/diff information, updating page revision numbers, updating RecentChanges pages, sending email notifications, etc.
  • Skin templates are now required to have <!--HTMLHeader?--> and <!--HTMLFooter?--> directives. Setting $EnableSkinDiag causes PmWiki to return an error if this isn't the case for a loaded skin. Skins that explicitly do not want HTMLHeader? or HTMLFooter? sections can use <!--NoHTMLHeader?--> and <!--NoHTMLFooter?--> to suppress the warning.
  • Added a new "pre" wikistyle for preformatted text blocks.
  • The xlpage-utf-8.php script now understands how to space UTF-8 wikiwords.
  • Searches on utf-8 site are now case-insensitive for utf-8 characters.
  • Many Abort() calls now provide a link to pages on pmwiki.org that can explain the problem in more detail and provide troubleshooting assistance.
  • PmWiki no longer reports "?cannot acquire lockfile" if the visitor is simply browsing pages or performing other read-only actions.
  • The $EnableReadOnly configuration variable can be set to signal PmWiki that it is to run in "read-only" mode (e.g., for distribution on read-only media). Attempts to perform actions that write to the disk are either ignored or raise an error via Abort().
  • Including authuser.php no longer automatically calls ResolvePageName?().
  • Authentication using Active Directory is now simplified. In Site.AuthUser or the $AuthUser variable, set "ldap://name.of.ad.server/" with no additional path information (see PmWiki.AuthUser for more details).
  • Pages are now saved with a "charset=" attribute to identify the character set in effect when the page was saved.
  • The phpdiff.php algorithm has been optimized to be smarter about finding smaller diffs.
  • Removed the (deprecated) "#wikileft h1" and "#wikileft h5" styles from the pmwiki default skin.
  • The mailposts.php and compat1x.php scripts have been removed from the distribution.

Version 2.1.27 (2006-12-11)

This version backports from 2.2.0-beta a bugfix for $TableRowIndexMax and also support for the {*$Variable} markup.

Version 2.1.26 (2006-09-11)

This version fixes a bug in feeds.php that would cause feed entries to be mixed up.

Version 2.1.25 (2006-09-08)

This release fixes a bug in authuser.php introduced by the 2.1.24 release.

The skin template code has also been extended to allow <!--XMLHeader--> and <!--XMLFooter--> as aliases for <!--HTMLHeader--> and <!--HTMLFooter-->.

Version 2.1.24 (2006-09-06)

This release makes some improvements and fixes to the AuthUser capability.

A bug in authuser.php that had trouble dealing with non-array values in $AuthUser has been fixed.

It is now possible to specify group memberships from local/config.php (remember that such entries must come before including the authuser.php script):

    # alice and bob's passwords
    $AuthUser['alice'] = crypt('alicepassword');
    $AuthUser['bob'] = crypt('bobpassword');

    # members of the @writers and @admins groups
    $AuthUser['@writers'] = array('alice',  'bob');
    $AuthUser['@admins'] = array('alice', 'dave');

    # carol is a member of @editors and @writers
    $AuthUser['carol'] = array('@editors', '@writers');

AuthUser can now read from Apache-formatted .htgroup files. The location of the .htgroup file can be done either in local/config.php or Site.AuthUser

    # local/config.php:
    $AuthUser['htgroup'] = '/path/to/.htgroup';

    # Site.AuthUser
    htgroup: /path/to/.htgroup

Versions 2.1.21, 2.1.22, 2.1.23 (2006-09-05, 2006-09-06)

This release closes a potential security vulnerability for sites that are running with 'register_globals' set to on. Details of the vulnerability will be forthcoming on the mailing list and site.

Sites that are running with PHP 'register_globals' and 'allow_url_fopen' set to 'On' should upgrade to this release at the earliest opportunity. If upgrading isn't an option, contact Pm for a patch to older versions.

There is now a tool available to analyze PmWiki sites for security and other configuration settings, see PmWiki:SiteAnalyzer.

Version 2.1.23 also corrects a bug that prevented PmWiki from being able to read pagefiles created by versions of PmWiki before 0.5.6.

Version 2.1.20 (2006-09-04)

More minor bugfixes:

  • Corrected a bug with WikiWord references appearing in the (:attachlist:) markup.
  • Restore ability to remove/override PmWiki's default CSS settings.

Version 2.1.19 (2006-08-30)

This release provides a number of very minor bugfixes and enhancements:

  • Fixed a bug in the pageindex code that was causing it to not regenerate as quickly as it should.
  • Fixed image/object/embed handling in wikistyles to better support the Cookbook:Flash recipe.
  • Fixed a bug with wikistyles and input form tags.

The next release(s) may have a number of substantial code enhancements and changes, so this release simply closes out a few items before introducing those changes.

Version 2.1.18 (2006-08-28)

This release closes a potential cross-site scripting vulnerability that could allow authors to inject Javascript code through the various table markups.

The release also adds a new (:input image:) markup to generate image input tags in forms.

Finally, this release corrects a problem with ?action=print failing to properly set the {$Action} page variable.

Version 2.1.17 (2006-08-26)

This release fixes a long-standing bug with $EnableIMSCaching (PITS:00573), whereby login/logout operations wouldn't invalidate browser caches, causing some people to see versions of a page prior to the login/logout taking place.

The new IMS caching code maintains a "imstime" cookie in the visitor's browser that keeps track of the time of last login, logout, author name change, or site modification. This cookie is then used to determine the proper response to browser requests containing If-Modified-Since headers. (Previously only the time of the last site modification was available.)

Browsers which do not accept cookies will effectively act as though IMS caching is disabled.

Version 2.1.16 (2006-08-26)

This release makes some improvements to skin handling -- primarily this improves the capability of relocating skin files to other locations, and to provide the ability for recipes to insert items at the end of HTML output.

This release introduces a <!--HTMLFooter--> directive into skin templates, which allows recipes and local customizations to insert output near the end of a document using a $HTMLFooterFmt array from PHP.

Also, the <!--HeaderText--> directive, which inserts the contents of $HTMLHeaderFmt into the output, has now been renamed to <!--HTMLHeader-->. PmWiki will continue to recognize <!--HeaderText--> to preserve compatibility with existing skins, but <!--HTMLHeader--> is preferred.

A new $SkinLibDirs array has been introduced which allows the source locations and urls for skins to be specified from a customization file. By default $SkinLibDirs is set as

  $SkinLibDirs = array("./pub/skins/\$Skin"      => "$PubDirUrl/skins/\$Skin",
                  "$FarmD/pub/skins/\$Skin" => "$FarmPubDirUrl/skins/\$Skin");

The keys (on the left) indicate the places to look for a "skin .tmpl file" in the filesystem, while the values (on the right) indicate the url location of the "skin css file". Modifying the value of $SkinLibDirs allows a skin .tmpl file to be located anywhere on the filesystem.

As far as I can see, none of the changes introduced by this release should have any sort of negative impact on existing sites, so it should be safe to upgrade. (If I'm wrong, please let me know.)

Version 2.1.15 (2006-08-25)

This release includes a number of feature enhancements and code cleanups as reported or requested by administrators.

First, AuthUser's LDAP authentication system now allows the use of a ?filter parameter, consistent with urls used for mod_auth_ldap authorization in Apache. See the newly updated LDAP section of the AuthUser documentation for more details.

A chicken-and-egg problem with the @_site_* authorization groups has been resolved. It's now possible to have a page's read authorization refer to things such as _site_edit.

Also, the RetrieveAuthPage?() function -- used for retrieving pages only if the visitor is authorized to do so -- now recognizes a special level parameter of 'ALWAYS', which means to always authorize access regardless of the browser or visitors current permissions. This may be useful for allowing certain operations to take place from within trusted scripts without having to grant full authorization to the browser.

Hardcoded instances of the local/ directory now use a customizable $LocalDir variable. This variable controls where PmWiki looks for local/config.php and per-group customization files. It may be useful for some Wiki Farm contexts. Note that this does not change or affect the location of $FarmD/local/farmconfig.php.

Some minor internal changes have been made to scripts/wikistyles.php to better accommodate the wikipublisher recipe. It's probably better if we don't try to explain them. :-)

Version 2.1.13, 2.1.14 (2006-08-15, 2006-08-16)

This release fixes a bug in handling numeric passwords, and also allows ldaps:// authentication sources.

Version 2.1.12 (2006-08-07)

This version introduces the ability to nest divs and tables. The standard (:table:) and (:div:) markups are still available, except that a (:div:) may contain a (:table:) and vice-versa.

As in previous versions of PmWiki, the (:div:) markup automatically closes any previous (:div:). However, there are now (:div1:), (:div2:), etc. markups (and the corresponding (:div1end:), (:div2end:), ...) which can be used to uniquely distinguish divs for nesting purposes.

To restore PmWiki's previous "non-nested" div behavior, set $Transition['nodivnest'] = 1; in a local customization file.

Other changes in this release:

  • Add a (:noaction:) directive to suppress display of page actions.
  • Allow anchor tags to contain colons, hyphens, and dots.
  • Add "white-space" as an allowed wikistyle.
  • Other minor bug fixes and typographical corrections.

Version 2.1.11 (2006-06-09)

This is a minor update that prevents %define=% wikistyles from generating empty paragraphs in the HTML output. Prior to this release, markup lines containing only wikistyle definitions would often generate empty paragraphs (<p></p>), this release changes things so that a markup line beginning with %define= and containing only wikistyle definitions will not initiate a new paragraph.

Version 2.1.10 (2006-06-03)

Version 2.1.4 introduced an {$Action} page variable that would contain the current ?action= value. Unfortunately, this page variable conflicted with a pre-existing $Action global variable that was being used by skins to display a human-friendly form of the current action. Since there's not really a clean way to resolve this, I've decided to keep {$Action} as a page variable with the current action value (as introduced in 2.1.4), and change the global for skins to be $ActionTitle. This will require updating skins to use $ActionTitle instead of $Action. I apologize for the conflict.

This release adds a Site.LocalTemplates page for the fmt=#xyz option in pagelist and search results. The list of pages to be searched can be customized via the $FPLTemplatePageFmt variable. The fmt=#xyz option will now also search the current page for a matching template before searching Site.LocalTemplates and Site.PageListTemplates.

The 'pmwiki' skin now places a <span> around the "Recent Changes" link in the header to make it somewhat easier to style.

Version 2.1.9 (2006-06-02)

This release fixes a long-standing and difficult-to-find bug with the handling of [[~Author]] links.

Version 2.1.8 (2006-06-01)

This release simply changes the $NotifyListFmt variable to be $NotifyListPageFmt (more descriptive), and adds a $NotifyList array that can be used to specify notification entries from a configuration file.

Version 2.1.7 (2006-05-31)

This release introduces a variety of improvements and bugfixes.

Vspace paragraphs are now divs: Version 2.1.7 changes the way that PmWiki handles vertical space in output (the infamous <p class='vspace></p> sequence). Instead of using paragraphs, PmWiki now generates <div class='vspace'></div> for vertical space sequences. In addition, PmWiki is able to collapse the vspace <div> with any subsequent paragraph tags, such that a sequence like

    <div class='vspace></div><p>...paragraph text...</p>

is automatically converted to

    <p class='vspace'>...paragraph text...</p>

This allows for better control over paragraph spacing. It is expected that this change in vspace handling will not have any detrimental effects on existing sites. Sites that have set custom values for $HTMLVSpace will continue to use the custom value. A site that wants to restore PmWiki's earlier handling of vspace can do so by adding the following to local/config.php:

    $HTMLVSpace = "<p class='vspace'></p>";

Improved email notifications of changes: Version 2.1.7 incorporates a notify.php script that provides improved capabilities for sending email notifications in response to page changes. This script is intended to replace the previous MailPosts capability, which is now deprecated (but will continue to be supported in PmWiki 2.1.x). Details and instructions for using notify.php are in the PmWiki.Notify page.

Added 'group home page' syntax: A group name followed by only a dot or slash is automatically treated as a reference to the group's home page, whatever it happens to be. This simplifies some pagelist templates as well as a number of other items. In particular, group links in pagelist output now points to the correct locations (instead of being a page in the current group).

Several bugs and vulnerabilities have been fixed:

  • The default width of edit forms is now more appropriate for Internet Explorer.
  • Authentication failure messages from LDAP are now suppressed.
  • Some cross-site scripting vulnerabilities in uploads and page links have been corrected (courtesy Moritz Naumann, http://moritz-naumann.com).
  • A problem with invalid pagenames resulting in redirect loops has been corrected.

Version 2.1.6 (2006-05-22)

The primary improvement in this release is the addition of a pagename argument to the (:if auth:) conditional markup. Thus one can display markup based on a visitor's authorization to a page other than the current one. For example, to test for edit privileges to Main.WikiSandbox, one would use (:if auth edit Main.WikiSandbox:). As before, if the pagename is omitted the directive tests authorization to the current page.

This release also restores the ability to have hyphens in InterMap link names.

Lastly, the release closes a potential cross-site scripting vulnerability in the WikiTrail markup, and provides some small performance improvements.

Version 2.1.4, 2.1.5 (2006-03-29)

This release fixes a few more bugs:

  • Pagelist-based feeds using ?action=rss work again.
  • Multi-term searches with special characters is fixed.

The release also adds a couple of items:

  • There is now an {$Action} page variable.
  • Usernames and passwords submitted to authuser.php can contain quotes.
  • The (:attachlist:) command now uses a natural case sort.

Version 2.1.3 (2006-03-17)

This release fixes a bug that prevents the lines= option from working on sites running PHP 5.1.1 or later. It also re-fixes a bug involving empty passwords and LDAP authentication.

Version 2.1.2 (2006-03-16)

This release fixes a bug with handling "nopass" passwords. It also makes some speed improvements to large web feeds, and fixes a couple of minor HTML tag mismatches.

Version 2.1.1 (2006-03-13)

This release primarily fixes a bug with passwords containing multiple authorization groups, and in the process slightly liberalized the formatting of "@group" and "id:name" handling. This release also adds a new mechanism for managing and displaying FAQ pages.

Version 2.1.0 (2006-03-12)

This set of release notes is fairly lengthy, as it chronicles all of the changes since 2.0.13 (four months of development). A lot remains the same, but some changes warrant extra care when upgrading from a 2.0.x version to 2.1.0 (thus the major revision number change). As always, questions and issues can be mailed to the pmwiki-users mailing list.

Here's the list:

  • WikiWords are now disabled by default. To enable them, set "$LinkWikiWords = 1;" in a local customization file. As of 2.1.beta2, you can now leave WikiWords enabled but have links to non-existent pages display without decoration -- to do this, place the following lines in pub/css/local.css:
    span.wikiword a.createlink { display:none; }
    span.wikiword a.createlinktext 
      { border-bottom:none; text-decoration:none; color:inherit; }
  • The (:pagelist:) code has been substantially revised. Pagelist formatting can now be specified using markup, and several defaults are available from Site.PageListTemplates. Also, several built-in pagelist formatting functions (FPLSimple?, FPLByGroup, FPLGroup?) are now removed in favor of the template code. The FPLByGroup function can be restored by setting $Transition['fplbygroup']=1; . Remark: Check to see if your page Site.PageListTemplates is not passwordprotected for viewing, otherwise the resulting pagelist will not be shown.
  • (:pagelist:) now also understands wildcards in group= and name= arguments, as well as excluding specific names and groups.
  • (:pagelist:) now has an "order=random" option.
  • (:searchbox:) now accepts "group=", "link=", "list=", etc. options to be passed along to the search results. It also accepts a "target=" option that identifies the page on which to send the search query.
  • ?action=search will display the contents of the current page if it contains a (:searchresults:) directive, otherwise it uses the content of the page identified by $PageSearchForm (default is the search page for the current language translation).
  • PmWiki no longer maintains a ".linkindex" file -- it now has a ".pageindex" file that contains not only a table of links, but also words used in each page (to speed up term searches). The maintenance of the .pageindex file can be disabled by setting $PageIndexFile='';
  • The $EnablePageListProtect variable now defaults to true, so that read-only pages appear in pagelists only if the visitor has read authorization. Note that this can also slow down some (:pagelist:) and search commands, so if the site doesn't have any read-only pages or if you aren't worried with cloaking read-only pages from searchlists, it might be worth setting $EnablePageListProtect=0; .
  • Whitespace indentation rules now exist and are enabled by default. Any line that begins with whitespace and aligns with a previous list item is considered to be "within" that list item. Text folds and wraps as normal, and the (:linebreaks:) directive is honored. To turn off whitespace indentation, use DisableMarkup('^ws');.
  • A single blank line after a !!Heading is silently ignored.
  • The (:redirect:) directive is now a true markup, and can be embedded inside conditional markups or includes. It also allows redirecting to an anchor in a page, such as (:redirect PageName#anchor:). A new from= option allows the redirect to take place only from pages that match the given wildcard specification. The status= option allows a 301, 302, 303, or 307 HTTP status code to be returned.
  • The built-in authorization function has gone through some substantial internal changes, however these changes should be fully backward compatible so that it doesn't impact any existing sites. (If it does cause a problem, please let me know so I can investigate why!) The password prompts are now specified by an admin-customizable Site.AuthForm page. In addition, the authorization function no longer creates PHP sessions for visitors that aren't being authenticated.
  • The authuser.php has likewise been substantially updated. The new version should have complete backwards compatibility with previous authuser.php settings, but this version also offers the ability to configure authentication resources and authorization groups through the Site.AuthUser page. Note that by default the Site.AuthUser page can only be edited using the admin password.
  • The $EnableSessionPasswords variable can be used to control whether passwords are held in PHP sessions. (This does not affect user authentication via AuthUser, however.)
  • The $Author variable now defaults to $AuthId if not otherwise set by a script or cookie.
  • The Site.SideBar page now defaults its edit password to the sitewide edit password (in $DefaultPasswords['edit']).
  • PmWiki now supports a "draft edit" mode, enabled by $EnableDrafts = 1. This creates a "Save as draft" button that will save a page under a "-Draft" suffix, for intermediate edits.
  • There is now an ?action=login action available.
  • A potential security vulnerability for sites running PHP 5 with register_globals enabled has been fixed.
  • The [[PageName |+]] markup is now available by default; this creates a link to PageName and uses that page's title as the link text.
  • What used to be "markup variables" are now "page variables". These are always specified using the {$variable} syntax, and can be used in markup and in $...Fmt strings. In addition, one can request a value for a specific page by placing the pagename in front of the variable, as in {pagename$variable}.
  • The scripts/rss.php script is now scripts/feeds.php, and is a complete redesign for web feed generation. The new version supports UTF-8 and other encodings, can generate Atom 1.0 (?action=atom), Dublin Core Metadata (?action=dc) output, and enclosures for podcasting. It also allows feeds to be generated from trails, groups, categories, and backlinks, and provides options (same as pagelists) for sorting and filtering the contents of the feed. Most sites can simply switch to using include_once("scripts/feeds.php"); instead of the previous rss.php include. The rss.php file has been removed from the distribution (but still works with PmWiki 2.1 for those sites that wish to continue using it).
  • InterMap entries can now come from a Site.InterMap page as well as the local/localmap.txt and local/farmmap.txt files. The format of these files has changed slightly, in that the InterMap name should now have a colon after it (previously the colon was omitted).
  • We can now provide better control of robot (webcrawler) interactions with a site to reduce server load and bandwidth. The $RobotPattern variable is used to detect robots based on the user-agent string, and any actions not listed in the $RobotActions array will return a 403 Forbidden response to robots. In addition, setting $EnableRobotCloakActions will eliminate any forbidden ?action= values from page links returned to robots, which will reduce bandwidth loads from robots even further (PITS:00563).
  • Non-existent page handling has been improved; whenever a browser hits a non-existent page, PmWiki returns the contents of Site.PageNotFound and a 404 ("Not Found") status code.
  • Page links that have "?action=" in their query arguments are now treated as "existing page" links even if the page does not exist.
  • The PmWiki default skin now adds rel='nofollow' to various action links.
  • Some of the CSS styles in the PmWiki default skin have been changed for better presentation.
  • The gui edit buttons have transparent (instead of white) borders so they integrate better into skins.
  • The $EnableIMSCaching variable is now much smarter, it can detect changes in local customization files as well as pages.
  • WikiStyles can now make percentage specifications by using "pct" to mean "%".
  • Class attributes in WikiStyle shortcuts are now cumulative, so that %class1 class2% results in class='class1 class2' instead of just class='class2' in the output.
  • A problem with the (:include PageName#from#:) markup not working has been fixed (PITS:00560).
  • Viewing a GroupHeader or GroupFooter page no longer displays the contents twice.
  • It's now easier to share pages among multiple sites (e.g., WikiFarms), see Cookbook:SharedPages (PITS:00459).
  • A problem with nested apostrophe markups has been fixed (PITS:00590).
  • PmWiki is now smarter about not surrounding block HTML tags with <p>...</p> tags.
  • If an [[#anchor]] is used more than once in a page, only the first generates an actual anchor (to preserve XHTML validity).
  • There are now (:if equal ...:) and (:if exists pagename:) conditional markups.
  • Compound conditional markup expressions are now possible -- e.g. (:if [ group PmWiki && ! name PmWiki ] :) .
  • Added an $InputValues array that can supply default values for certain form controls (PITS:00566).
  • The default setting of $UploadUrlFmt is now based on $PubDirUrl instead of $ScriptUrl.
  • The $text global variable has been removed (use $_GET['text'], $_POST['text'], or $_REQUEST['text']).
  • A possible problem with url-encoding of attachments with non-ASCII characters has been addressed (PITS:00588).
  • Page actions in non-existent pages no longer display with non-existent link decorations.
  • A README.txt file has been added, and several documentation files are now available through the docs/ directory.
  • PmWiki is no longer available through CVS on sourceforge.net. It is now available via SVN on pmwiki.org, at svn://pmwiki.org/pmwiki/tags/latest . For more details, see PmWiki:Subversion.
  • The $NewlineXXX variable (deprecated in 2.0.0) has been removed.
  • There is experimental support for server-side caching of pages that take a long time to render; this is currently an unsupported feature and may be removed in future releases.

Wiki administrators should note that from this release on PmWiki defaults to having WikiWords disabled.

To make sure WikiWords are enabled, use $LinkWikiWords = 1; in the local/config.php file.


Bugs and other requests can be reported to the PmWiki Issue Tracking System at http://www.pmwiki.org/wiki/PITS/PITS. Any help in testing, development, and/or documentation is greatly appreciated..

Release Notes archive - notes for versions older than 2.1.0.


ChangeLog

See the cookbook recent changes page for additional updates and activity by other developers, or join the PmWiki mailing lists to discuss feature development with us.

Version 2.2.44 (2012-10-21)

  • Better display of whitespace in page histories.
  • Fix definition for PageTextVariables containing a dash (PITS:00978).
  • Update documentation.

Version 2.2.43 (2012-09-20)

  • Allow for HTML attribute names to contain dashes, eg. data-transition, data-role etc.
  • Remove warning when previewing Site.EditForm.
  • Update documentation.

Version 2.2.42 (2012-08-20)

  • Convert the line-endings in the docs/ directory to \r\n compatible with Windows.
  • Modify PHSC() to call htmlspecialchars() with a single-byte encoding argument.
  • Update documentation.

Version 2.2.41 (2012-08-12)

  • Change $KeepToken to "\034\034" which is compatible with more encodings.
  • Update documentation.

Version 2.2.40 (2012-07-21)

  • Add PHSC() helper function as a replacement of htmlspecialchars() for PHP 5.4 (PITS:01292).
  • Update documentation.

Version 2.2.39 (2012-06-25)

  • Fix URL encoding of attachment links.
  • Update documentation.

Version 2.2.38 (2012-05-21)

  • Fix "Wrong parameter count for utf8_decode" warning, reported by Simon.
  • Update documentation.

Version 2.2.37 (2012-05-01)

  • Add page filename encoding functions.
  • Better handling of dots in [[#anchor_1.2]] sections (PITS:01285).
  • Expand PageVariables in PageList? template defaults (PITS:01282).
  • Add test for iconv() and mb_convert_encoding(), refactor recode().
  • Update documentation.

Version 2.2.36 (2011-12-28)

  • Add $EnableOldCharset variable and $page["=oldcharset"] entry.
  • Refactor PageStore?->recode() to recover Windows-1252 characters.
  • Add exit line to xlpage-iso-8859-2.php (PITS:01275).
  • Fix difference in defining and removing "invisible" PTVs?.
  • Update documentation.

Version 2.2.35 (2011-11-11)

  • Fix critical PHP injection vulnerability (PITS:01271, reported by Egidio Romano).
  • Important change: Disable script loading from XLPage?().
  • Move the processing of [[link|+]] inside LinkPage?() and delete markup rule from stdmarkup.php.
  • Modify MakeLink() to better handle link titles.
  • Add optional $LinkTitleFunction allowing recipes to customize the link titles.
  • Fix ReadTrail?() to better handle links with titles.
  • Add title attributes for the HTML templates in the $LinkPage*Fmt variables.
  • Add upload extensions svg, xcf, ogg, flac, ogv, mp4, webm, odg, epub.
  • Minor optimization for the MarkupExpressions for UTF-8 strings.
  • Minor optimization of the rendering of page history.

Version 2.2.34 (2011-10-10)

  • Add MarkupExpressions replacements for UTF-8.
  • Reset timestamps of Site(Admin).AuthUser to 1000000000, used in upgrades.php.
  • Update documentation.

Version 2.2.33 (2011-09-23)

  • Fix locked states for Site and SiteAdmin? GroupAttributes (reported by Brijesh Kothari).
  • Fix intermap.txt entries PITS: and Wikipedia: to point to their current locations.
  • Fix refcount.php to produce valid HTML (PITS:01266).

Version 2.2.32 (2011-09-18)

  • Add required html xmlns attribute to the print skin template.
  • Add PageStore?->recode() function.
  • Add $DefaultPageCharset array.
  • Optimize for speed the inline diff for page history when too many lines were added or deleted.
  • Update and convert to UTF-8 the documentation.

Note: Due to a manipulation error, a version 2.2.31 was created before it was ready for a release.

Version 2.2.30 (2011-08-13)

  • Fix $Charset definition in iso-8859-*.php files.
  • Add $EnableRangeMatchUTF8, set it to 1 to enable range matches in UTF-8.
  • Update documentation.

Version 2.2.29 (2011-07-24)

  • Fix Attach links that were broken with the Path fix in 2.2.28.
  • Add $IMapLocalPath array containing InterMap prefixes that should be treated as local.

Version 2.2.28 (2011-07-24)

Version 2.2.27 (2011-06-19)

  • Add block WikiStyle %justify% (PITS:01253).
  • Remove unused <vspace> after a redirection (PITS:01255).
  • Add ?nodiff=1 parameter for page history to disable diff rendering and show only restore links.
  • Update documentation.

Version 2.2.26 (2011-05-21)

Version 2.2.25 (2011-03-22)

  • Update documentation.

Version 2.2.24 (2011-02-15)

  • Add {$$PageTrailDepth} pseudovariable for pagelist templates.
  • Fix PageVar?(), add $authpage array for an authenticated page data, removed $EnablePageVarAuth.
  • Update documentation.

Version 2.2.23 (2011-01-25)

Version 2.2.22 (2011-01-16)

Version 2.2.21 (2010-12-14)

  • Fix potential XSS vulnerability, reported by DFaure?.
  • Fix invalid HTML for simple table captions, reported by JL.
  • Fix WikiStyles could work not properly if a value was empty like accesskey="".

Version 2.2.20 (2010-12-14)

  • Fix Pagelist {$$variable} didn't work in template none (PITS:01212).
  • Fix interface access keys in browse mode (PITS:01188).
  • Add PmL10n?: intermap prefix for the Localization/ group on pmwiki.org (PITS:01180).
  • Fix AuthUser excluding members didn't work (PITS:01201).
  • Update documentation.

Version 2.2.19 (2010-11-10)

  • Update documentation.

Version 2.2.18 (2010-09-04)

  • Fix $SaveAttrPatterns to skip nested conditionals (reported by RandyB?).
  • Fix RecentChanges when an edit summary contains the dollar sign (PITS:01217).
  • Fix RDF feed number of elements (PITS:01198).
  • Update documentation.

Version 2.2.17 (2010-06-20)

Version 2.2.16 (2010-05-10)

  • Allow "exists" conditional to accept wildcards (PITS:01184)
  • Fix GUI button %center% which didn't work correctly.
  • Fix incorrectly parsed quote in PQA(), possible script injection (discovered by Hanno Boeck).

Version 2.2.15 (2010-03-27)

  • Add (Auth|Edit)Form to auto-translated titles.
  • Fix (:if auth LEVEL:) to respect $HandleAuth (PITS:01164).
  • Skip loading of the second half of draft.php if $action!="edit".
  • Fix bug with (:template none:) introduced in 2.2.14, reported by Holger.
  • Fix HandleDownload?() to use binary file-read.

Version 2.2.14 (2010-02-27)

Version 2.2.13 (2010-02-21)

  • Replace deprecated in PHP 5.3 function split() with explode().
  • Add $WordDiffFunction default to PHPDiff?().
  • Use existing border colors as highlighting background.
  • Refactor/optimize DiffRenderSource?(), merge with DiffRenderInline?().
  • Change default history to show word-level highlighting.
  • Fix bug with $DiffKeepNum which kept less revisions than it should.
  • Fix RetrieveAuthPage?() call from HandleDiff?().
  • Update documentation.

Version 2.2.12 (2010-02-17)

  • Allow a custom $DiffHTMLFunction to skip the line rendering if it returns false.
  • Add $EnableDiffInline, simple word-level diffs (PITS:00571).
  • Update documentation.

Version 2.2.11 (2010-02-14)

Version 2.2.9, 2.2.10 (2010-01-17)

Version 2.2.8 (2009-12-07)

  • Fix apostrophes in Author field (PITS:01155).
  • Fix Condition "exists" for PHP 5.3 (PITS:01156).
  • Update documentation.

Version 2.2.7 (2009-11-08)

Version 2.2.6 (2009-10-04)

Version 2.2.5 (2009-08-25)

  • Add *.7z as accepted upload extension (PITS:00813).
  • Fix global variable $HandleAttrFmt in HandleAttr? (PITS:01126).
  • Allow brackets in input element names (PITS:01131).
  • Fix CSS class applied twice (PITS:01071).
  • Fix Not-Modified headers could prevent caching (PITS:00802).
  • Break FPLTemplate() into configurable sub-parts (PITS:01102).
  • Add (:template none:) section for Pagelist templates.
  • Fix attr-protected page could be deleted with edit permissions (PITS:00238).
  • Update documentation.

Version 2.2.4 (2009-07-16)

  • Fix bug with page attributes, which somehow didn't make it in the 2.2.3 release.
  • Fix bug with HTML entities in XLPages? introduced earlier today in 2.2.3 (reverted, PITS:01114).

Version 2.2.3 (2009-07-16)

Version 2.2.2 (2009-06-21)

Version 2.2.1 (2009-03-28)

  • Fix $FPLTemplateMarkupFunction which somehow didn't get in the 2.2.0 archive.
  • Fix wikitrails to work cross-group (PITS:00407).
  • Add $EnableRedirectQuiet variable (PITS:00919).
  • Fix {$Title} could display global variables (reported by HansB?).
  • Fix reloaded form submissions could lose values (reported by DaveG).
  • Fix preview while restoring a version from history (PITS:01081).
  • Fix relative links with international characters (reported by G. Hermanowicz).
  • Add in sample-config.php example call to xlpage-utf-8.php (PITS:01066).
  • Update documentation.
  • Fix guiedit.php to produce valid HTML.

Version 2.2.0 (2009-01-18)

  • Convert beta series to official release series.
  • Add $FPLTemplateMarkupFunction (PITS:00984, requested by John Rankin).

Version 2.2.0-beta68 (2008-08-14)

  • Fix E_NOTICE errors reported by Dominique Faure.
  • Enable (:redirect:) directives in pagelists.

Version 2.2.0-beta67 (2008-07-13)

Version 2.2.0-beta66 (2008-07-04)

  • Add content-type/charset to Abort() output (suggested by Petko).
  • Close minor XSS vulnerability (PITS:01030).
  • Add "nested if" capability.
  • Fix bug in $Transition handling that would enable all transitions if any were set (reported by John Rankin).

Version 2.2.0-beta65 (2007-11-17)

  • Fix SiteAdmin.AuthList so that it defaults to list=all (reported by Roman).
  • Fix pmwiki skin to include xmlns= attribute in <html> tag (PITS:00989, reported by Mateusz Czaplinski and Petko Yotov).

Version 2.2.0-beta64 (2007-11-13)

  • Add times to PmWiki date parsing (e.g., 2007-08-09T12:22:04).
  • Suppress warning from ini_set in diag.php (suggested by Petko).
  • Fix handling of -> links in trails (reported by Eemeli Aro).
  • Add .kml and .kmz as valid attachment types.
  • Fix handling of &amp; in markup (PITS:00988, reported by Stirling Westrup).
  • Fix duplication of language markers in $XLLangs (PITS:00987, reported by Stirling Westrup).
  • Correct typo in DRange?() call in stdmarkup.php (reported by Stirling Westrup).
  • Turn on error displays when diagnostics are enabled.
  • Default PHP's pcre.backtrack_limit to at least 1000000.

Version 2.2.0-beta63 (2007-07-31)

  • Added $SkinDirectivesPattern to allow adjustments to available skin directives (requested by Petko).
  • Fix default permissions on Site.AuthUser and Site.AuthList (reported by Scott Connard).
  • Add "monospace" to pmwiki.css default (reported by Joshua Timberman, with assistance from H. Fox)
  • Fix problem with slashes in wildcards to name= and group= parameters (reported by Ian MacGregor?).

Version 2.2.0-beta62 (2007-07-21)

  • Fix bug in trails introduced by beta61 (reported by charlequin).

Version 2.2.0-beta61 (2007-07-19)

  • Add ability to grab trails by section.
  • Add an "ontrail" condition (from suggestions by charlequin).

Version 2.2.0-beta59, 2.2.0-beta60 (2007-07-18)

  • Fix problem with upgrade.php on wiki farms (reported by Scott Connard).
  • Fix problem with distributed version of Site.AuthUser (reported by Jon Haupt).

Version 2.2.0-beta58 (2007-07-17)

Version 2.2.0-beta57 (2007-06-15)

  • Fix AsSpacedUTF8?() to work like AsSpaced?() (reported by Petko).
  • Qualify page links that contain parentheses (reported by Petko).
  • Fix bug in (:input default $:var ... :) (reported by Crisses).

Version 2.2.0-beta56 (2007-06-13)

  • Fix AsSpaced?() to not add spaces before leading digit, and treat hyphenated digits as complete numbers.
  • Fix infinite recursion in self-referencing page text variables (PITS:00915).
  • Fix bug introduced in beta55 not handling end anchors correctly (reported by Roman).

Version 2.2.0-beta55 (2007-06-11)

Version 2.2.0-beta53, 2.2.0-beta54 (2007-06-02)

  • Improve error message reporting for markup rules (suggestion by Knut Alboldt).
  • Clean up more E_NOTICE warnings (reported by Ian MacGregor?).
  • Add focus= option to (:input:) controls.
  • Added CSS .faqtoc class, to be able to display only the questions coming from the #includefaq page list template.
  • Changed PmWiki.FAQ to use .faqtoc class.
  • Fix bug in TextSection? (PITS:00935, reported by Jean-Fabrice).
  • Fix bug in page list caching of trails.

Version 2.2.0-beta52 (2007-05-26)

  • Add per-PageStore? attributes (from a suggestion by Tobias Thelen).
  • Add {$PasswdRead}, {$PasswdEdit}, etc. to display page password settings.
  • Add Site.AuthList to display all password permissions on a site.
  • Reorder $PageListFilters slightly.
  • Add "passwd=" option to page list, to return only those pages that have some sort of password attribute on them.
  • Add line numbers to StopWatchHTML? output.
  • Clean up handling of $AuthCascade.

Version 2.2.0-beta51 (2007-05-23)

  • Add fmt=count to page list (reminder from Hans).
  • Ignore hidden files in skin directories when searching for .tmpl (suggestion by Stephan Becker).
  • Clean up queuing of pages to be updated in .pageindex .
  • Reset $LinkTargets() at beginning of each UpdatePage() sequence.

Version 2.2.0-beta50 (2007-05-22)

  • Fix HTML cache when drafts are enabled, or other recipes using CondAuth().
  • Prevent page lists with protected pages from HTML cache.

Version 2.2.0-beta48, 2.2.0-beta49 (2007-05-21)

  • Fix spurious value= attribute in <textarea> tag generated by (:input textarea ... :).
  • Allow either (:input default ...:) or (:input defaults ...:).
  • Fix problem with page text variable handling in (:input defaults:).
  • Allow either (:template default:) or (:template defaults:) in page list templates.
  • Fix a bug handling dates with suffixes (reported by Crisses).

Version 2.2.0-beta47 (2007-05-20)

  • Fix bug with quote handling in (:include:) options (reported by Hans).

Version 2.2.0-beta46 (2007-05-19)

  • Moved $PageTextVarPatterns definition from scripts/stdmarkup.php to pmwiki.php.
  • Ignore Markup() rules that have unresolved $when parameters.
  • Fix issue in authuser.php when $auth array isn't set (contributed by Ben Stallings).
  • The (:include:) directive now performs template argument processing on the included text.
  • Optimized (:pagelist:) slightly when sorting on page variables.
  • Refactored (:input ... :) markups.
  • Added HandleDispatch?(), which allows action handlers to easily redispatch to other actions (and add messages).
  • Added FmtTemplateVars?(), to perform various template-substitutions.

Version 2.2.0-beta45 (2007-05-02)

  • Update pmwiki's date parsing to use a common routine, recognizing dates within strings and restricting range to 1900-2039.
  • Add additional parameter to "date" conditional.
  • Add if= option to page list (suggested by Crisses).
  • Refactor code to use TextSection?() and RetrieveAuthSection?() functions.
  • The value= parameter to (:input textarea:) now works properly (including values loaded from $InputValues).
  • The (:input default:) directive now allows loading input control defaults from another page via the source= parameter.
  • Remove automatic call to FmtPageName() in $ROSPatterns. Add $ROEPatterns (from suggestions by JB and others).
  • Fix minor variable bugs in scripts/crypt.php.
  • Remove E_NOTICE errors (reported by Hans).
  • Fix handling of page variables when pagename is empty or not provided.
  • Add $EnableLinkPageRelative configuration option.
  • Clean up handling of arguments to {(ftime ...)}.
  • Remove mailposts.php call in stdconfig.php (reported by Christophe David).

Version 2.2.0-beta44 (2007-04-16)

  • Fix case conversion of U+027D and U+026B (reported by Petko).
  • Add $FTimeFmt to set default formatting for {(ftime)}.
  • Add %s conversion to {(ftime)} for systems that don't have it by default.
  • Report an error if edit form cannot be read (suggested by Hans).
  • Don't report ?cannot acquire lockfile when simply browsing pages.
  • Add $EnableReadOnly flag to signal when PmWiki is to be run in read-only mode.

Version 2.2.0-beta43 (2007-04-15)

  • Update drafts code to add $EnablePublishAttr and change button labels when drafts are enabled (PITS:00755).
  • Removed no-longer-needed 'compat1x.php' and 'mailposts.php' from distribution.
  • Added $DraftRecentChangesFmt.
  • Added "markup expressions" {(...)} into the core.
  • Added charset= attribute to saved pages.
  • Update pagelist.php and xlpage-utf-8.php to handle case-insensitive searches.
  • Added some optimizations to phpdiff.php script to produce more useful history information.

Version 2.2.0-beta42 (2007-03-27)

  • Fix a bug with order=title in pagelists (reported by Anno).

Version 2.2.0-beta41 (2007-03-26)

  • Added $EnableWSPre option, which allows easy adjustment of the "leading space -> preformatted text" (or "whitespace") rule.
  • Added a new "pre" wikistyle, to designate blocks that are to be treated as preformatted text.

Version 2.2.0-beta40 (2007-03-24)

  • Fix bug with order=title in pagelists when using $Titlespaced (PITS:00906, reported by Feral).
  • Report state of allow_url_fopen when downloads fail in blocklist.php.

Version 2.2.0-beta39 (2007-03-23)

  • Allow page variable filters to appear as options in (:template defaults:) (reported by SteP?).
  • Updated Site.PageListTemplates to use (:template:) directives.
  • Remove '#wikileft h1' and '#wikileft h5' from pmwiki default stylesheet.

Version 2.2.0-beta38 (2007-03-22)

  • Strip control characters from $ChangeSummary.
  • Fix problem with count=m..n where m..n is outside the range of available pages (reported by SteP?).
  • Allow (:template default ...:) to specify a class= option.
  • Redirect pagename can now include an anchor (PITS:00558)

Version 2.2.0-beta37 (2007-03-16)

  • Allow an optional space after comma separators in wildcard patterns (reported by Han Baas).

Version 2.2.0-beta36 (2007-03-16)

  • Allow nested page text variables to work, remove extraneous ENT_NOQUOTES parameter.
  • Add new (:template ...:) directives for pagelist templates.
  • Modify count= option to pagelists to allow for alternate ranges.

Version 2.2.0-beta35 (2007-03-05)

Version 2.2.0-beta33, 2.2.0-beta34 (2007-03-01)

  • Refactor wildcard handling into its own GlobToPCRE? function.
  • Allow negated wildcards for page variable filters in pagelists (PITS:00878, reported by Jiri)
  • Fix wildcards so that spaces no longer separate patterns (use commas).
  • Fix handling of '&' prior to (:input:) and other directives (reported by Luigi).
  • Adjust position of %define=...% wiki styles to occur after ampersands.
  • Adjust copyright dates on many files.
  • Allow spaces around text variable names in page text variable markups.

Version 2.2.0-beta32 (2007-02-28)

  • Fix erroneous $EnableCreole item in docs/sample-config.php (reported by Sigurd).
  • Added (:elseif:) and (:else:) markups (PITS:00787).
  • Fix global $Skin variable handling when using SetSkin? from within markup.
  • Make sure directives aren't treated like page text variables (reported by Petko).
  • Remove call to ResolvePageName?() from authuser.php .
  • Simplify LDAP authentication for Active Directory sites.
  • Cache lowercase/uppercase patterns in AsSpacedUTF8?().

Version 2.2.0-beta31 (2007-02-11)

Version 2.2.0-beta29, 2.2.0-beta30 (2007-02-09)

  • MakePageName? now uses the first matching entry of $PagePathFmt as the home page of groups without a home page.
  • Add AsSpacedUTF8?() to handle title spacing in utf-8 (PITS:00875, contributed by Petko, Celok)
  • Fix $RequestedPage when running with utf-8.
  • Add <meta> content-type tag for utf-8.
  • Add an experimental caching system for pagelists.
  • Fix $SuffixPattern and link suffixes for utf-8 (PITS:00881, reported by ppip).

Version 2.2.0-beta28 (2007-02-03)

  • Update blocklist.php so that all posted fields are checked for block values (PITS:00850).

Version 2.2.0-beta27 (2007-01-25)

  • Fix markup processing sequence for (:input default:), (:input select:), etc. (problem noted by Marc).
  • Fix default value of order= parameter to MakePageList?().

Version 2.2.0-beta26 (2007-01-23)

  • Fix a bug where pagelist list= option had no effect when reading from trails (from an rss problem noted by Russ Fink).

Version 2.2.0-beta24, 2.2.0-beta25 (2007-01-22)

  • Add a scripts/creole.php module for Creole markup (http://www.wikicreole.org/).
  • Move WikiWords out of the core defaults -- can be enabled via $EnableWikiWords.
  • Fix handling of WikiWords following & or #, as in &AElig; and #FFFF00 (reported by Moni Kellermann).
  • Adjust FormatTableRow?() to support Creole-style tables (using single |'s).
  • Update docs/sample-config.php with new configurations and options.
  • Added code to allow Abort() to refer to additional information on pmwiki.org.
  • Added $EnableSkinDiag, which checks templates for required <!--HTMLHeader?--> and <!--HTMLFooter?--> directives.
  • Removed deprecated $BasicLayoutVars support from skins.php.

Version 2.2.0-beta22, 2.2.0-beta23 (2007-01-17)

  • Added $EnableActions, to allow pmwiki.php to be included without generating output (from a suggestion by Wouter Groeneveld).
  • Fix bug in "order=" option to (:pagelist:) (reported by Mike Bishop).
  • Change DisplayStopWatch?() function to StopWatchHTML?().
  • Allow multiple lines for markup:, wiki:, and page: template directives (reported by Marc)

Version 2.2.0-beta21 (2007-01-12)

  • Fix <vspace> bug in searchresults output (PITS:00846, reported by M. Czaplinski, marc, and others).
  • Fix numerous E_NOTICE warnings and incorrect constants (PITS:00853, contributed by AndrewFyfe?).

Version 2.2.0-beta20 (2007-01-11)

  • $FeedPageListOpt needs to be declared global in feeds.php.
  • Add "404 Not Found" status code to ?invalid page name aborts (PITS:00854, suggested by Athan).
  • Remove stale entries from $PageExistsCache when a new PageStore? is added (reported by Hans).

Version 2.2.0-beta19 (2006-12-29)

  • Have blocklist check $_POST['text'] only when it is set (from a report by Simon).

Version 2.2.0-beta18 (2006-12-28)

  • Change $pagename parameter in UpdatePage() to be passed by reference (suggestion by J. Meijer).
  • Fix $EnableRobotsCloakActions so that it works again with page variables.
  • Add "XML Sitemaps" to $RobotPattern.
  • Change $MetaRobots to return "nofollow,noindex" for non-existent pages.
  • Prefer "404 Not Found" to "403 Forbidden" for robots attempting to do invalid actions on non-existent pages.
  • Add rel='nofollow' to "create attachment" links.
  • Added class='inputbox' to select boxes (suggested by Hans).
  • Added .odt, .ods, and .odp file extensions to allowed uploads (suggested by Algis Kabaila, Robin Sheat, and others).
  • Clean up some error warnings (PITS:00801, contributed by psvo).
  • Set $ScriptUrl to 'https:' when accessed via SSL link (suggestions from C. Ridderström, H. Fox, PITS:00410, PITS:00527, PITS:00595).
  • Fix bug in link= and trail= options to (:pagelist:) (reported by C. Ridderström).

Version 2.2.0-beta17 (2006-12-13)

  • Fix spurious hidden field in (:searchbox:) output (reported by Hans).
  • Fix $CaseConversions array for \xc4\xb1 and \xc5\xbf (reported by Petko Yotov).
  • Refactor (:input:) markup handling.
  • Add (:input select ...:) markup (PITS:00567).
  • Add (:input default ...:) markup -- may change before 2.2.0 release.
  • Add ability to set defaults for radio/checkbox/select controls.

Version 2.2.0-beta16 (2006-11-10)

  • Fix problem with (:e_preview:) directive when viewing an edit form (reported by Dominique Faure).
  • Fix out-of-memory problem in scripts/compat1x.php when dealing with large pages to be converted (contributed by Donald Gordon).
  • Fix problem of Variable: lines immediately followed by newline (reported by Hans).
  • Fix uninitialized variable errors in FormatTableRow?() (reported by Bob Sanders).
  • Fix second argument of MakeBaseName?() (provided by Stirling Westrup).

Version 2.2.0-beta15 (2006-10-16)

  • Fix bug with displaying multi-line (:var:value:) page text variables (reported by Pico).
  • Improve PageStore? ls() method slightly, to restrict pagename searches to directories of a given depth (based on an issue reported by Chris Cox).
  • Added $IsBlocked status variable to scripts/blocklist.php.
  • Added $UnapprovedLink array to report unapproved links.
  • Added $TimeISOFmt, $TimeISOZFmt, and $CurrentTimeISO variables.
  • Switched scripts/feeds.php to use $TimeISOZFmt instead of $ISOTimeFmt.
  • Added request= option to (:pagelist:), switched pagelist to default to not use url/form parameters.
  • Fixed bug with array {$$options} in pagelist.

Version 2.2.0-beta14 (2006-10-06)

Version 2.2.0-beta13 (2006-10-04)

  • Fix handling of angle brackets (and potential XSS) in pagelists combined with page text variables (noted by Pico).

Version 2.2.0-beta12 (2006-10-03)

Version 2.2.0-beta11 (2006-10-03)

  • Added ability to automatically create targets.
  • Added sample code to docs/sample-config.php for automatic generation of Category.* pages.
  • Fixed character escapes in pagelist {$$option} variables.

Version 2.2.0-beta10 (2006-10-02)

  • Added {$$option} variables to get option values from (:pagelist:) (based on a recipe from Martin Fick).
  • Changed {$PageCount}, {$GroupPageCount}, and {$GroupCount} to be {$$PageCount}, {$$GroupPageCount}, and {$$GroupCount}.
  • Added {$BaseName} page variable and $BaseNamePatterns.

Version 2.2.0-beta9 (2006-10-01)

  • Fix bug with $EnablePageListProtect (reported by Brent Zupp).
  • Added ability to select based on page variables in (:pagelist:).

Version 2.2.0-beta8 (2006-09-30)

  • Update scripts/blocklist.php to check only $_POST['text'] instead of entire markup text.
  • Fix bug in pagelist.php that wouldn't return correctly formatted array in certain circumstances (noted by Florian Fischer and JDem?).

Version 2.2.0-beta7 (2006-09-30)

  • Added scripts/blocklist.php to core.
  • Updated handling of $PageTextVarPatterns.
  • Eliminated need for extra flush() steps in notify.php, pagelist.php.

Version 2.2.0-beta6 (2006-09-27)

  • Fix bug with initialization of $FeedPageListOpt in scripts/feeds.php (reported by Roman).
  • Fix bug with over-eager (:textvar:value:) markup (from a bug reported by Chris Cox).

Version 2.2.0-beta4, 2.2.0-beta5 (2006-09-27)

  • Fix bug with name= option in pagelist (reported by Ben Wilson).
  • Fix bug with array_merge under PHP 5 (reported by Kathryn Andersen).

Version 2.2.0-beta3 (2006-09-26)

  • Remove extra <!----> comment at end of table directives (noted by Ben Stallings).
  • Fix directive form of page text variables (reported by Kathryn Andersen).
  • Add first version of new modular pagelist code.

Version 2.2.0-beta2 (2006-09-25)

  • Add support for {$:var} page text variables, and (:var:...:) markup.
  • Fix default setting of $EnableRelativePageVars in docs/sample-config.php .

Version 2.2.0-beta1 (2006-09-25)

  • Added {*$var} page variables (always the currently browsed page).
  • Convert link and page variable handling in (:include:) to be relative to the included page.
  • Added $EnableRelativePageVars and $EnableRelativePageLinks variables, as well as transition options.
  • Added basepage= option to (:include:).
  • Updated $GroupHeaderFmt and $GroupFooterFmt to use basepage= option.
  • Adjusted $MakePageNamePatterns to automatically strip any #... or ?... from the end of a pagename input string (solution to a problem reported by J. Meijer).

Version 2.1.27 (2006-12-11)

  • Backport in bug fix for TableRowFormat? (from 2.2.0-beta16).
  • Add support for {*$Variable} syntax (from 2.2.0 page variables).

Version 2.1.26 (2006-09-11)

  • Fix a bug with variable referencing that caused feeds.php to get a confused PCache? (reported by Helge Larsen).

Version 2.1.25 (2006-09-08)

  • Fixed a bug in authuser.php that would fail if $AuthUser isn't defined (reported by Hans Huijgen).
  • Added <!--XMLHeader?--> and <!--XMLFooter?--> aliases to <!--HTMLHeader?--> and <!--HTMLFooter?--> directives in skin templates (suggested by John Rankin).
  • Added $PageExistsCache (suggested by John Rankin).

Version 2.1.24 (2006-09-06)

  • Fixed a bug in authuser.php that had trouble dealing with non-array entries in $AuthUser (reported by Udo).
  • Can now specify authorization groups using $AuthUser['@group'] entries.
  • Can now specify an Apache .htgroup-formatted file for authorization groups via $AuthUser['htgroup'].

Versions 2.1.21, 2.1.22, 2.1.23 (2006-09-05, 2006-09-06)

  • Close a potential security hole with $FarmD when register_globals is set "On".
  • Correct a syntax error in feeds.php (noted by Ben Wilson).
  • Fix a bug that prevented PmWiki from reading page files generated by versions prior to 0.5.6 (discovered by Milan Avramovic).

Version 2.1.20 (2006-09-04)

  • Fixed a bug in (:attachlist:) when passed a wikiword argument (reported by Kathryn Andersen).
  • Changed $HTMLStylesFmt['markup'] to honor config.php setting (reported by Hans).

Version 2.1.19 (2006-08-30)

  • Corrected a bug in the pageindex code that was causing the .pageindex to not update as quickly as it should.
  • Slightly changed the handling of 'width' and 'height' in wikistyles.php, so that they can be be applied as attributes to <object> and <embed> tags.
  • Updated the Keep() function to recognize closing block tags as being in the 'B' block pool.
  • Fixed a bug with wikistyles and form tags.

Version 2.1.18 (2006-08-28)

  • Closed a potential cross-site scripting vulnerability in table markups (reported by JB).
  • Added (:input image:) markup (requested by JB).
  • Fixed problem with ?action=print failing to set {$Action} (reported by Bart).

Version 2.1.17 (2006-08-26)

  • Added some improvements to IMS caching to better handle logout and authorization actions (PITS:00573, reported by floozy and Henrik Bechmann).

Version 2.1.16 (2006-08-26)

  • Added $SkinLibDirs variable, to select filesystem and url locations where skins may be found (resolves PITS:00708, as reported by Hagan Fox, with additional suggestions from Ben Wilson).
  • Changed <!--HeaderText--> to <!--HTMLHeader--> in skin templates, and added an optional <!--HTMLFooter--> directive (PITS:00767).
  • Adjusted the pmwiki and print skins to use the new directives.

Version 2.1.15 (2006-08-25)

  • Fixed issue dealing with order of @_site_* passwords (reported by Jean-Fabrice and others).
  • Added $LocalDir variable (requested by John Rankin).
  • Removed an unnecessary setting of $DefaultPage in scripts/pgcust.php (it's now handled by ResolvePageName?() ).
  • Added some variables and changes in wikistyles.php to better support wikipublisher (contributed by John Rankin).
  • RetrieveAuthPage? (PmWikiAuth?) now recognizes a $level of 'ALWAYS' as indicating that access should always be allowed, regardless of current passwords or identities.
  • Added filter specifier for AuthUser LDAP authentication (contributed by Balu).

Version 2.1.13, 2.1.14 (2006-08-15, 2006-08-16)

  • Updated scripts/authuser.php to allow ldaps://... authentications (contributed by Michael Brenner).
  • Fixed problem with numeric passwords introduced in 2.1.beta20 (reported by Christophe David and Dirk Blaas).

Version 2.1.12 (2006-08-07)

  • Corrected typo in Site.SideBar file (reported by Judith Zacharie).
  • Suppressed warning message for search on sites without a wikilib.d/ directory.
  • Added capability for nested divs.
  • Use $Transition['nodivnest'] to restore previous non-nesting div/table behavior.
  • Including authuser.php now automatically resolves pagename.
  • Added (:noaction:) directive to turn off actions.
  • Fixed bug in wikistyles prior to image blocks.
  • Added white-space as allowed wikistyle (suggested by C. Ridderström).
  • Allow colons, hyphens, and dots in id= tags.

Version 2.1.11 (2006-06-09)

  • Fixed generation of empty paragraphs around %define=...% wikistyles (PITS:00753).

Version 2.1.10 (2006-06-04)

  • Added a <span> around the RecentChanges link in the pmwiki skin (PITS:00750, suggested by Hagan Fox).
  • Changed the $Action variable to $ActionTitle (PITS:00749, reported by Hagan Fox).
  • Changed $FPLTemplatePageFmt to be an array of pages to be searched for page templates, enabled searching of current page and Site.LocalTemplates page.
  • Updated .vspace margin in sidebar for pmwiki skin (PITS:00751, by Hagan Fox).

Version 2.1.9 (2006-06-02)

  • Fixed a bug with [[~Author]] links (PITS:00530 reported by Klonk, PITS:00611 reported by weijang, PITS:00671 reported by Stirling Westrup, and helpful clues provided by Clayton Curtis).

Version 2.1.8 (2006-06-01)

  • Added ability to specify notification entries from local/config.php as well as Site.Notify (suggested by Christophe David).
  • Fixed $Transition['vspace'] from 2.1.7.

Version 2.1.7 (2006-05-31)

  • Adjusted width of edit form for IE browsers (contributed by Roman and H. Fox).
  • Suppress authentication failure error from LDAP (PITS:00739).
  • Fixed problem with invalid page names resulting in redirect loop (PITS:00723, reported by jojoo).
  • Added "Group." and "Group/" page name syntax, resolving PITS:00736 (from a suggestion by Pico).
  • Changed handling of "vspace" paragraphs.
  • Fixed some XSS vulnerabilities in uploads.php and url links (reported by Moritz Naumann, http://moritz-naumann.com).
  • Added notify.php script, allowing finer control of email notifications.

Version 2.1.6 (2006-05-22)

  • Optimized performance of urlapprove.php.
  • Added (:if auth xyz PageName:) syntax.
  • Corrected XSS bug in trails.php.
  • Slightly improved performance of free links.
  • Restore ability to use hyphens in InterMap links (reported by Henrik Bechmann).

Version 2.1.4, 2.1.5 (2006-03-29)

  • Fixed problem with pagelist-based feeds (PITS:00709, reported by Jon Haupt).
  • Added {$Action} page variable. (PITS:00696, reported by Sebastian Pipping).
  • Added stripmagic() around variables submitted to authuser.php.
  • Fixed problem with multi-term searches containing special characters (PITS:00713, reported by Leo).
  • Switched (:attachlist:) to use a natural case sort (suggested by H. Fox).

Version 2.1.3 (2006-03-17)

  • Re-fixed problem with PHP 5.1.1 and lines= option to (:include:) (PITS:00620).
  • Fixed empty LDAP password issue (reported by Thomas Lederer).

Version 2.1.2 (2006-03-16)

  • Fixed <h1>/<h2> tag mismatches (PITS:00702, reported by Martin Hason).
  • Fixed bug with $AllowPassword and "nopass" (reported by M. Weiner and bram brambring).
  • Improved the speed of RSS and other web feeds when $EnablePageListProtect is not set.

Version 2.1.1 (2006-03-13)

  • Fixed a bug with multiple authorization groups as a password (PITS:00699, reported by Ari Epstein).
  • Updated the authorization code to be a bit more liberal with password/group settings.
  • Updated PmWiki.FAQ page to be able to grab FAQ items from other pages in the documentation.

Version 2.1.0 (2006-03-12)

  • Many many documentation updates (special thanks to many authors).
  • Allow trailing underscores in upload names (requested by Hans).
  • Fixed 'ak_print' problem causing accesskey='a' for print (noted by Pico).
  • Added code to make sure each anchor is generated only once per page (for XHTML validity).
  • Added a $BlockPattern variable to recognize block HTML tags.
  • Made an adjustment to Keep() so that it places strings with block HTML into the 'B' pool.
  • Adjusted stdmarkup.php to not produce paragraphs for keep blocks in the 'B' pool.
  • Corrected a variety of i18n phrases.
  • Added class='escaped' to distinguish @@...@@ from [@...@] (from a comment by Hans).
  • Slightly changed styling of .faq divs.
  • Made the edit textarea a couple of rows smaller to better fit on smaller displays (suggested by H. Fox).

ChangeLog Archive - changes prior to version 2.1.0.


Glossary

This page describes various terms related to PmWiki.

Author
Any user with privileges to write to the wiki.
Admin
The person (or people) who controls access to the wiki, configures the wiki, and generally is the person who installed the wiki.
Configuration file
A specially-named PHP script file where local customizations can take place for a farm, a wiki, a group, or a page.
Default configuration
The way Pm has chosen to set all settings, or an individual setting, by default. For example, $EnablePathInfo is disabled by default. A wiki with no local/config.php file is using the default configuration. Likewise, a farm that only defines $FarmPubDirUrl in farmconfig.php is using the default configuration.

Farm
A group of wikis that share code. Content and formats may or may not be shared. For more farm-related terms, including several which have been deprecated, see WikiFarmTerminology
Farm-wide configuration file
A WikiFarm?'s local/farmconfig.php file, where any settings (besides $FarmPubDirUrl) customize the default configuration for all of the wikis in a farm.
Full page name
The full page name consists of a group and a name, e.g. Main.WikiSandbox. The variable for the full page name is {$FullName}, which for this page is Test.IncludeAll. Similarly, the variable for the group is {$Group} which here is Test.
Group
A collection of associated wiki pages; by default this appears in the page name as "Group.PageName?". Attributes can be set on all pages in the group simultaneously. The variable for the group is {$Group}, which here is Test.
Local configuration file
A specially-named PHP script where local customizations can take place for an individual wiki. For an entire wiki it's named local/config.php. Individual groups and pages can also have their own local configuration files.
Local customization
Any deviation from the default configuration. A related phrase is "farm-wide customization".
Page file name
The page file name is the name of the file that normally stores the data of a page in the directory wiki.d/. This file name is normally built directly from the page name.
Page link
A page link is something that is used to generate a link to a page. For example, the markup [[wiki sandbox]], [[(wiki) sandbox]], WikiSandbox, Main/WikiSandbox, [[Main/wiki sandbox]], [[Main.WikiSandbox | click here]], etc all specify a link to the page 'Main.WikiSandbox'. In each case PmWiki uses the context of the link to generate a page name from the page link -- normally by capitalizing each word found in the link and stripping any characters that aren't considered valid in page names.
Page name
The page name is a string that PmWiki uses to refer to a page - i.e. it names the page. This could also be considered a handle for the page. The variable for the page name is simply called {$Name}, which for this page is IncludeAll.
Note that there is no whitespace in page names, and by default PmWiki capitalizes each word in a page's name. There is however a variable {$Namespaced} where spaces have been inserted, e.g. for the page WikiSandbox this variable would be Wiki Sandbox.
Note that PmWiki also uses the page name to locate per-group and per-page customization files in the local/ subdirectory. For example, browsing Main.WikiSandbox would cause local/Main.WikiSandbox.php and local/Main.php to be loaded if these files existed.
Page title
A page title is the title element of a page, i.e. what is usually shown above the page and in the browser window's name. This title is normally set via the directive (:title:), but if no such directive is given the title will be automatically generated from the page name. The title of a page is accessed via either the variable {$Title} or the variable {$Titlespaced}. The latter differs in that it uses the spaced version of the name.
Page URI
Page names are used in URIs to tell PmWiki which page is to be loaded or acted upon. The normal form of a page URI is usually one of these two
http://www.example.com/pmwiki/pmwiki.php?n=Main.WikiSandbox
http://www.example.com/pmwiki/pmwiki.php/Main.WikiSandbox
Note that various aliasing and rewriting tricks can be used to modify this, but PmWiki expects to obtain a page name from the parameter 'n' or from the PATH_INFO component following the URI of the script (pmwiki.php).
Note that the parameter 'n' takes precedence over PATH_INFO if both are available.
Wikifarm
Synonymous for "farm".

BasicVariables

Where the variables are available as wiki markup they are shown as Variable value "{$VariableName?}".

%apply=item id=AsSpacedFunction?%$AsSpacedFunction
The name of the function used to convert WikiWords into normal, spaced strings. Defaults to 'AsSpaced?'.
$AsSpacedFunction = 'MyAsSpaced';

Variable value ""

$Author
Set to the current reader, who is potentially an author (see discussion). See also $EnablePostAuthorRequired.
%apply=item id=AuthorGroup?%$AuthorGroup
The WikiGroup for user profiles. Defaults to 'Profiles'. This variable is implicit in the markup [[~AuthorName]]
$AuthorGroup = 'Users';
%apply=item id=AuthId?%$AuthId
For sites using user-based authorization, tracks the "reader" or login name.
SessionAuth($pagename);
if( isset($AuthId) ) { // this person has been authenticated
%apply=item id=AuthPw%$AuthPw
Request for documentation, meanwhile see here.
SessionAuth($pagename);
if( isset($AuthPw) ) { // this person has entered a password

Variable value "Test.IncludeAll"

%apply=item id=BaseName%$BaseName
%apply=item id=BaseNamePatterns?%$BaseNamePatterns
Allows population of the {$BaseName} PageVariable. The key to the hash is the pattern to be replaced and the value is the replacement string.
# If {$FullName} is 'Group.Page-Draft' then {$BaseName} is 'Group.Page'
$BaseNamePatterns['/-Draft$/'] = '';
# If {$FullName} is 'Comments-Group.Page' then {$BaseName} is 'Group.Page'
$BaseNamePatterns['/^Comments-/'] = '';
%apply=item id=CategoryGroup?%$CategoryGroup
The WikiGroup used for categories. Defaults to 'Category'. (See Categories). This variable is implicit in the markup [[!CategoryName]]
%apply=item id=CookiePrefix?%$CookiePrefix
A string prefix to be prepended to cookies set from PmWiki scripts. It defaults to '', but can be set to a different value to avoid conflicts with similar-named cookies from other applications, or to allow multiple wikis from the same domain to store separate cookies.
$CookiePrefix = 'pmwiki_'; # set cookie prefix to 'pmwiki_'
If you have a WikiFarm, use the following in each field's config.php to get a unique prefix for each field in the farm, thus isolating each field's cookies.
$CookiePrefix = substr($tmp = md5(__FILE__), 0, 5).'_';

Variable value "PmWiki"

%apply=item id=DefaultGroup?%$DefaultGroup
WikiGroup used by default (on startup) when no group is specified in the URL.

Variable value "HomePage"

%apply=item id=DefaultName?%$DefaultName
Name of the default HomePage of each WikiGroup. Used when the group doesn't have a page with the same name as the group.
%apply=item id=DefaultPage?%$DefaultPage
Startup page when PmWiki is called without a specified page, normally $DefaultGroup.$DefaultName.
Note: for $DefaultGroup, $DefaultName and $DefaultPage variables to work, they should be defined in the beginning of (farm)config.php, before any call to the function ResolvePageName?(). This means, before any script from PmWiki and before any recipe that might be using this function.
%apply=item id=EnableLocalConfig?%$EnableLocalConfig
Allows/disables local/config.php customizations (usually for a farm's wikis). Can be set to zero in local/farmconfig.php to prevent the farm's wikis' local/config.php from being loaded.
$EnableLocalConfig = 0; # disable PmWiki's local/config
%apply=item id=EnablePGCust?%$EnablePGCust
Allows/disables per-page and per-group customizations. Can be set to zero in any local customization file to prevent remaining page/group customizations from being loaded.
$EnablePGCust=0; # turn off per-page/group configs
%apply=item id=EnableRedirect?%$EnableRedirect
When enabled (default), causes page redirects to automatically be performed by the browser. Setting $EnableRedirect to zero causes PmWiki to pause and issue a "Redirect to link" message instead. This is sometimes useful when debugging recipes to be able to see the results of actions before page redirections occur.
%apply=item id=EnableWikiWords?%$EnableWikiWords
Enable WikiWord processing.
%apply=item id=EnableWSPre?%$EnableWSPre
Enables a markup rule that causes lines with leading spaces to be treated as sections of preformatted text. If set to a value greater than 1, indicates the minimum number of leading spaces required for this treatment.
$EnableWSPre = 1; # leading spaces are preformatted text
$EnableWSPre = 0; # leading spaces are normal lines of text
$EnableWSPre = 4; # 4+ spaces are preformatted text
%apply=item id=FTimeFmt?%$FTimeFmt
Can be used to override the default date format used by the "ftime" function. The default $FTimeFmt is $TimeFmt. (See Markup Expressions)
%apply=item id=GroupPattern?%$GroupPattern
The regular expression pattern used for valid WikiGroup name specifications. Defaults to allowing any group name beginning with an uppercase letter, but can be set to limit the valid group names (see Cookbook:LimitWikiGroups).
# limit groups to Site, SiteAdmin, PmWiki, and MyGroup
$GroupPattern = '(?:Site|SiteAdmin|PmWiki|MyGroup)';
#for case-sensitive group names, note the ?-i switch:
$GroupPattern = '(?-i:Site|SiteAdmin|PmWiki|MyGroup)';
%apply=item id=LinkWikiWords?%$LinkWikiWords
If set, then bare WikiWords in a page are automatically linked to pages of the same name. Note that this value can also be affected by the (:linkwikiwords:) and (:nolinkwikiwords:) directives.
$LinkWikiWords = 1; # turn on WikiWord links
$LinkWikiWords = 0; # disable WikiWord links
Note, this setting requires WikiWords to be enabled, see $EnableWikiWords.
%apply=item id=LogoutRedirectFmt?%$LogoutRedirectFmt
Identifies the page to which the visitor should be sent after an ?action=logout. Defaults to the current page.
$LogoutRedirectFmt = 'Site.Logout'; # ?action=logout target
%apply=item id=LogoutCookies?%$LogoutCookies
An array of cookie names to be removed when ?action=logout is invoked.
%apply=item id=NamePattern?%$NamePattern
The regular expression pattern used for valid page names. Defaults to allowing pages beginning with an uppercase letter or digit, followed by sequences of alphanumeric characters, hyphens, and underscores.

Variable value "Site"

%apply=item id=SiteGroup?%$SiteGroup
Default group for storing configuration and utility pages such as Site.Search, Site.EditForm, Site.PageNotFound, etc.
%apply=item id=SiteAdminGroup?%$SiteAdminGroup
Default group for locked administrative pages such as SiteAdmin.AuthList, SiteAdmin.AuthUser, SiteAdmin.ApprovedUrls, etc, defaults to 'SiteAdmin?'.
%apply=item id=SpaceWikiWords%$SpaceWikiWords
If set, then WikiWords in pages are automatically spaced according to $AsSpacedFunction. Note that this value can also be affected by the (:spacewikiwords:) and (:nospacewikiwords:) directives.
$SpaceWikiWords = 1; # turn on WikiWord spacing
$SpaceWikiWords = 0; # turn off WikiWord spacing
%apply=item id=TimeFmt?%$TimeFmt
The format to use for dates and times, in strftime() format. The default value is '%B %d, %Y at %I:%M %p', which gives dates of the form "September 8, 2005 at 10:57 PM".
$TimeFmt = '%B %d, %Y'; # dates as "September 8, 2005"
$TimeFmt = '%Y-%m-%d'; # dates as "2005-09-08"

Variable value "pmwiki-2.3.38"

$Version
A string representing the release version of PmWiki.

Variable value "2003038"

%apply=item id=VersionNum?%$VersionNum
A number representing the release version of PmWiki, with the major and minor release components padded with zeroes to produce three digits. Thus, release "pmwiki-2.1.40" will have $VersionNum set to 2001040.
The first digit is a 2, the next three digits are the major release number, and the last three digits are the minor release number. Beta releases use 900-999 for the minor release number. Thus:
2.1.0          2001000
2.1.1          2001001
...
2.1.27         2001027
2.2.0-beta1    2001901
2.2.0-beta2    2001902
...
2.2.0-beta18   2001918
...
2.2.0          2002000
%apply=item id=WikiWordPattern?%$WikiWordPattern
The pattern that describes a WikiWord.
%apply=item id=EnableRelativePageVars?%$EnableRelativePageVars
This setting controls how Page variables in included pages are understood by PmWiki.
$EnableRelativePageVars = 1; # PmWiki current default
In this case {$Name} displays the name of the physical page where it written. If {$Name} is in an included page, it will display the name of the included page. (This is currently PmWiki's default.)
$EnableRelativePageVars = 0; # revert to previous default
In this case {$Name} displays the name of the currently browsed page. Even if {$Name} is in an included page, it will display the name of the browsed page. This was PmWiki's default in versions 2.2.8 and earlier, and changed in 2.2.9, but you can revert it back with this line in config.php.
{*$Name} with an asterisk always displays the name of the currently browsed page, regardless of $EnableRelativePageVars.

EditVariables

To set many of the variables below specify them in config.php.

%apply=item id=AutoCreate?%$AutoCreate
Used in conjunction with the AutoCreateTargets? edit function, this array records any sets of pages which should be created automatically if they don't exist. The syntax is
$AutoCreate[REGEXP] = PAGE_PARAMETERS;
where REGEXP is a regular expression which will identify the pages to be autocreated, and PAGE_PARAMETERS is an array of attributes for the page to be created. For example,
$AutoCreate['/^Category\\./'] = array('ctime' => $Now);
will create a blank page with a current creation time for any missing Category page.
%apply=item id=DefaultPageTextFmt?%$DefaultPageTextFmt
The text that should be displayed when browsing non-existent pages. As default PmWiki uses the contents of Site.PageNotFound
$DefaultPageTextFmt = '(:include $[{$SiteGroup}.PageNotFound]:)';
%apply=item id=DeleteKeyPattern?%$DeleteKeyPattern
The pattern used to determine if a page should be deleted. The default is to remove pages that contain only the single word "delete" (and optional spaces).
# change delete word to "remove"
$DeleteKeyPattern = "^\\s*remove\\s*$";
# delete any page with no visible text, i.e., empty
$DeleteKeyPattern = "^\\s*$";
%apply=item id=DiffKeepDays?%$DiffKeepDays
The $DiffKeepDays variable sets the minimum length of time that a page's revision history is kept. By default it is set to 3650 days, or a little less than ten years. You can change this value in a customization file to be something smaller, e.g.:
$DiffKeepDays = 30; # keep revisions at least 30 days
Note that a specific page revision isn't removed from the page until the first edit after the time specified by $DiffKeepDays has elapsed. Thus, it's still possible for some pages to have revisions older than $DiffKeepDays -- such revisions will be removed the next time those pages are edited.
%apply=item id=DiffKeepNum?%$DiffKeepNum
This variable contains the minimum number of changes to be kept in the page history, even if some of them are older than the limit defined by $DiffKeepDays. It prevents lost history of pages that are older, but have few changes.
$DiffKeepNum = 50; # keep at least 50 revisions (default is 20)
%apply=item id=DraftSuffix?%$DraftSuffix
The suffix to use for draft versions of pages (default "-Draft").
%apply=item id=EditFunctions?%$EditFunctions
This array contains the sequence of functions that are called when a page is edited. It can be customized to provide additional functions to be called as part of the editing process. The standard setting is:
$EditFunctions = array('EditTemplate', 'RestorePage', 'ReplaceOnSave',
  'SaveAttributes', 'PostPage', 'PostRecentChanges', 'AutoCreateTargets', 'PreviewPage'); 
%apply=item id=EditRedirectFmt?%$EditRedirectFmt
The page to which an author is sent after pressing "Save" or "Cancel" from an edit form. Defaults to "$FullName", which sends the author to the page just edited, but can be changed to specify another page.
# redirect to Main.HomePage
$EditRedirectFmt = 'Main.HomePage';  
# redirect to HomePage of current group
$EditRedirectFmt = '{$Group}.HomePage';
%apply=item id=EditTemplatesFmt?%$EditTemplatesFmt
Name of the page (or an array of names) to be used as the default text for any newly created pages.
# Use 'Main.NewPageTemplate' as default text of all new pages
$EditTemplatesFmt = 'Main.NewPageTemplate';
# Use 'Template' in the current group for new pages
$EditTemplatesFmt = '$Group.Template';
# Use 'Template' in the current group if it exists, otherwise
# use 'Main.NewPageTemplate'
$EditTemplatesFmt = array('$Group.Template', 'Main.NewPageTemplate');
See Cookbook:EditTemplates for more information.
%apply=item id=EnableDrafts?%$EnableDrafts
When set to '1', enables the "Save draft" button and built-in handling of "draft" versions of pages, where:
  1. initial "Save draft" of an existing page ("PageName") saves changes to a new name ("PageName-Draft")
  2. subsequent attempts to edit PageName causes PageName-Draft to be edited
  3. subsequent selections of "Save draft" cause PageName-Draft to be saved
  4. pressing "Publish" causes PageName-Draft to be posted to PageName, and deleted.
# turn on draft edits
A related variable, $EnablePublishAttr, adds a new "publish" authorization level to distinguish editing of drafts from publishing them.
%apply=item id=EnableGUIButtons?%$EnableGUIButtons
When set to '1', turns on the graphical buttons in the "Edit Page" form.
# turn on graphical edit buttons
%apply=item id=EnablePostAuthorRequired?%$EnablePostAuthorRequired
When set to '1', posting of pages requires the author to provide an author name. Otherwise, authors can post without a name.
# require authors to provide a name
%apply=item id=HandleEditFmt?%$HandleEditFmt
Like $HandleBrowseFmt, this specifies the entire output format for ?action=edit for a page.
%apply=item id=IsPagePosted?%$IsPagePosted
Set to a true value if the page is actually saved (e.g., this is used to tell the RecentChanges handlers if they need to update).
%apply=item id=PageEditFmt?%$PageEditFmt
By default, this is the HTML to be displayed for an edit form.
%apply=item id=PageEditForm?%$PageEditForm
Specifies the edit form for ?action=edit. Defaults to '$SiteGroup.EditForm'.
%apply=item id=ROEPatterns?%$ROEPatterns
With this array you can add a pattern as key and set a text value which replace it on every edit request, using preg_replace function. Specifically it is replaced when the page is loaded into the editform, whenever a preview is done, and when the page is saved (from PmWiki 2.2.0beta45). See Cookbook:ROEPatterns for examples.
%apply=item id=ROSPatterns?%$ROSPatterns
With this array you can add patterns as key and set a text value which will replace it when the edited page is posted (as signaled by $EnablePost). It is not replaced when the page is loaded into the editform nor when a preview is done, but it is replaced only when the page is saved. See Cookbook:ROSPatterns for examples.

FilePermissions

This page briefly describes PmWiki's settings for file and directory permissions in a typical Unix environment.

Simple installation (out of the box)

First, let's look at PmWiki without any cookbook scripts loaded. PmWiki needs to be able to write into the

  • wiki.d/ directory to be able to save pages
  • uploads/ directory to save uploads.

Those are the *only* directories that need to be writable by the webserver. It doesn't matter to PmWiki who owns or creates those directories, as long as it has write permission to them.

Everything else should be owned by the account holder, and readable by the webserver account (but normally not writable by the webserver account).

That's it -- everything else depends on the specific PHP configuration and running environment, which is detailed below (and which is why there isn't a definitive answer that applies to every situation). But the above two rules are absolute and answer 95% of the questions about directory permissions.

On a Unix host the webserver typically runs with a userid and groupid that is different from the account holder. Usually the webserver account is something like "nobody", "apache", "www", or "httpd". Thus, in a standard installation, the account holder manually creates the wiki.d/ and uploads/ directories, and sets the permissions on the directories to be world-writable in order for PmWiki (running as the webserver account) to be able to create files there.

$ pwd
/home/pmichaud/public_html/pmwiki
$ mkdir uploads
$ mkdir wiki.d
$ chmod 777 uploads wiki.d        
$ ls -ld . uploads wiki.d
drwxr-xr-x   12 pmichaud pmichaud     1024 Feb 10 11:51 .         
drwxrwxrwx    8 pmichaud pmichaud     1024 Jan 23 11:58 uploads             
drwxrwxrwx    2 pmichaud pmichaud    54272 Feb 10 15:29 wiki.d      

Avoiding world-write directories

However, lots of people don't like having those world-writable (rwx) permissions on the directories. The only practical way to eliminate the world write permissions is if we can get the webserver and account holder to be the owner and group of the directories and the files within them. Since Unix typically doesn't allow non-superusers to change ownerships of files or directories that already exist, we have to make sure they are created with the correct ownerships in the first place.

To get the directories to be owned by the webserver account, we let PmWiki take care of creating them. This means we temporarily grant write permission to the parent, and then execute PmWiki to allow it to create the directories. However, we also want the newly created directories to have the same group as the account holder, so the account holder can remove or manipulate files in the directories. Therefore, we use Unix's setgid capability (2777 or 'rws' permissions) to cause all newly created files to inherit the same group as the parent.

To avoid world-write directories, use the following instructions instead of the instructions above. If you already have created the wiki.d/ and uploads/ directories, use chown and chmod to match the following results.

$ pwd
/home/pmichaud/public_html/pmwiki
$ chmod 2777 .  
$ ls -ld .
drwxrwsrwx  10 pmichaud pmichaud 4096 May 28 09:55 .
# <-- execute pmwiki.php script from web browser -->
$ ls -ld . uploads wiki.d
drwxrwsrwx  10 pmichaud pmichaud 4096 May 28 09:55 .
drwxrwsr-x   2 nobody   pmichaud 4096 May 28 09:55 uploads
drwxrwsr-x   2 nobody   pmichaud 4096 May 28 09:55 wiki.d
$ chmod 755 .
drwxr-xr-x  10 pmichaud pmichaud 4096 May 28 09:55 .
drwxrwsr-x   2 nobody   pmichaud 4096 May 28 09:55 uploads
drwxrwsr-x   2 nobody   pmichaud 4096 May 28 09:55 wiki.d

Now the two directories are owned by 'nobody', which means the webserver can write to them. We don't have world-writable permissions on the directories, and the account holder (pmichaud) still has write permissions to the files and directories by virtue of the group ownership and permissions. The setgid bit also ensures that any files or subdirectories created within uploads/ or wiki.d/ will belong to the same (pmichaud) group.

Safe mode

HOWEVER, if a site is running in PHP's "safe_mode", then the "let PmWiki create the directories" solution doesn't work, as PHP will only create files in directories that are owned by the same user that owns the pmwiki.php script itself. Thus, PmWiki (apache) cannot create the directories in this case, or safe_mode will complain when PmWiki attempts to write a file into those directories. The *only* way for things to work in safe_mode is to manually create the needed directories and set their permissions to 777, as outlined at the beginning of this section.

PHP running as script owner

There are some webservers and PHP installations that are configured to run a PHP script with the same identity as the owner of the script. This is often called "suexec PHP" or even just "suPHP". In this case, since the PmWiki script ends up running with the same identity as the account holder, then everything "just works" out of the box without doing anything manually. PmWiki creates any directories and files as needed, each owned by the account holder, and permissions aren't generally an issue at all.

Cookbook scripts

Okay, now let's look at cookbook scripts. If a cookbook script has files that it wants to make available to browsers, such files should generally be placed somewhere within the 'pub/' hierarchy and referenced via '$PubDirUrl'.

If a cookbook recipe needs to *write* files to disk, then the same rules apply to that directory as for the wiki.d/ and uploads/ directories above, with the exact ownerships and permissions depending on the webserver and PHP configuration. In general the cookbook recipe should do the same as PmWiki, and just call PmWiki's mkdirp($dir) function. PmWiki will then take care of creating the directory (if it can) or prompting for its creation as appropriate.

For example, if cookbook recipe 'frobot' wants to distribute a .css file, then that file should go somewhere like pub/css/frobot.css or pub/frobot/frobot.css. The directories and files in this case should be created and owned by the account owner, since the cookbook recipe doesn't need to create or modify any of the files when it runs.

As an alternate example, the Cookbook:MimeTeX recipe wants to be able to create cached images for the math markup, and those images need to be available to the browser. Thus, MimeTeX uses a pub/cache/ directory, which should be created in whatever manner was used to create the wiki.d/ and uploads/ directories (i.e., according to the webserver and PHP configuration). Again, Cookbook:MimeTeX just solves this by calling mkdirp("pub/cache"), and letting that function create the directory or prompt the administrator for the appropriate action based upon the server settings encountered.

See also


FmtPageName

This page describes an internal function in PmWiki's engine called FmtPageName(). The contents are not intended for those with a weak heart ;-)

Also see: PmWiki.Functions

FmtPageName($fmt, $pagename)

Returns $fmt, with $variable and internationalisation substitutions performed, under the assumption that the current page is pagename. As a rule is used to pre-process all variables which by convention have a "Fmt" suffix (like $GroupFooterFmt), but also other strings that require interpolation, notably the page template (.tmpl) file. See PmWiki.Variables for an (incomplete) list of available variables, PmWiki.Internationalizations for internationalisation.

The function FmtPageName() applies internationalization-substitutions and $Variable-substitions to the string $fmt under the assumption that the current page is $pagename.

The substitutions go as follows:

  1. Replace any sequences of the form $XyzFmt with value of any corresponding global variable.
  2. Process the string for any $[...] phrases (internationalized phrase), using the currently loaded translation tables.
  3. Replace any instances of {$ScriptUrl} with $ScriptUrl (to defer processing to the URI processing phase)
  4. Replace any instances of standard Page Variables (beginning with an upper case letter, followed by at least one word character) with their values. Note that PVs? of the form {Group.Page$Var} are not replaced. If there are no more $-sequences, then return the formatted string and exit the function
  5. Perform any pattern replacements from the array $FmtP. Typically this is used to handle things like $Name and $Group etc that are specific to the name of the current page. ?? Appears to be used in robots.php to hide actions from robots.
  6. Replace any remaining instances of Page Variables with their values. Note that these variables are in the form $Var rather than the usual PV form of {$Var}.
  7. If $EnablePathInfo isn't set, convert URIs to use the syntax $ScriptUrl?n=<Group>.<Name> instead of $ScriptUrl/<Group>/<Name>. In any case, replace $ScriptUrl with its value. If there are no more $-sequences, then return the formatted string and exit the function
  8. Replace any $-sequences with global variables (caching as needed) of the same name (in reverse alphabetical order, and filtering out any unsafe globals) *
  9. Replace any $-sequences with values out of the array $FmtV.

Note that FmtPageName() is automatically aware of any global variables. However, since modifying global variables may be expensive, the array $FmtV exists as a way to avoid rebuilding the variable cache for values that change frequently.

Security

According to PM, as a general rule it's unwise to be calling FmtPageName() on strings that are coming from page markup, as this exposes the ability for people to view the values of variables that perhaps they shouldn't see. This is also why page variables (which come from markup) use PageVar?() and PageTextVar?() and don't go through FmtPageName().

Availability of Variables in FmtPageName

To be very specific, here's what Pm wrote regarding different ways of defining a variable that can be used by FmtPageName (when it is formatting a string):

  • Set a global variable. FmtPageName() automatically performs substitution on all global variables that aren't arrays. If the variable is going to change value over repeated calls to FmtPageName, it's probably better to use $FmtV as in the next item.
  • Set a value in the $FmtV array. $FmtV['$MyVariable']='something' means to replace instances of '$MyVariable' with 'something'. Use this for variables that change value frequently over multiple calls to FmtPageName.
  • Set a pattern/replacement in the $FmtP array. This is normally done for substitutions that have to be dynamic somehow based on the pagename being referenced, such as '$Title', '$Group', '$Name', '$PageUrl', etc.

Also see: Cookbook:Functions#FmtPageName

Finally, here's something else Pm wrote that is related and explains why we have this function:

In order to produce its output, PmWiki has to do a variety of string substitutions:
  1. Generating the full name, group, title, or url of a page (other than the currently displayed page)
  2. Substituting the values of global variables
  3. Performing internationalization substitutions
  4. Converting $ScriptUrl/$Group/$Name to $ScriptUrl?n=$Group.$Name for sites that cannot handle PATH_INFO urls
  5. Other substitutions needed by specific functions
PmWiki centralizes all of that substitute-a-dynamic-value-in-a-string into the FmtPageName() subroutine. Because some things are extremely dynamic, such as the url or group for an arbitrary page that is not the current one, those things cannot be simple global PHP variables. Or, if they do become global variables, they're variables that cannot be trusted to hold a value for very long because some other routine (that may happen to be formatting a string for a different page) will come along and change that global variable for whatever it happens to be doing.
A limited set of $-substitutions -- basically anything that corresponds to a page attribute -- are not PHP variables and are only available through the FmtPageName() subroutine. The complete set of these special substitutions is $Group, $Name, $FullName, $PageUrl, $Title, $Titlespaced, $Namespaced, $Groupspaced, $LastModifiedBy, $LastModifiedHost, and $LastModified. These items cannot just be standard PHP variables because often PmWiki needs to obtain the url, name, group, title, etc. of a page other than the one currently being viewed by a browser.
At the moment, $Title, $LastModified, $LastModifiedBy, and $LastModifiedHost can only work if the page's attributes have been loaded and cached using the PCache function. So, to get at these values one must typically do:
$page = ReadPage($pagename);
PCache($pagename, $page);
$ptitle = FmtPageName('$Title', $pagename);
$pauthor = FmtPageName('$LastModifiedBy', $pagename);

I18nVariables

This page describes the variables used by PmWiki for Internationalizations (i18n).

%apply=item id=EnableXLPageScriptLoad?%$EnableXLPageScriptLoad
This variable, if set to 0, will disable the 'xlpage-i18n' parameter in XLPage? definitions and thus it will prevent editors from (accidentally) loading scripts and changing the website encoding. Note that if you use this variable, you should include the required scripts, eg. xlpage-utf-8.php, from config.php.
%apply=item id=VarPagesFmt?%$VarPagesFmt
An array which contains the PageNames? where you can find lists (trails) of pages containing variable definitions. To be modified when documentation is not in English. See scripts/vardoc.php.
$XL
An array (hash) which contains pairs of language identifiers and translation hashes. Each translation hash maps a given lookup key (or phrase) into a corresponding text string for the given language. Thus, it is essentially a multi-lingual dictionary used for phrase translation. It is also used for handling user preference mappings. Thus, the 'e_row' value that one finds on the Site.Preferences page is loaded into $XL during preference processing.
%apply=item id=XLLangs?%$XLLangs
An array that contains the names of the currently active language definitions. Only dictionaries in $XL that are named in $XLLangs are used by the $[...] markup when performing a translation.

See also:


LayoutVariables

Variable substitutions in the skin template are all managed by the FmtPageName() function from pmwiki.php. Pmwiki variable substitutions available on pages are managed by the substitutions from stdmarkup.php or superseded in local/config files.

%apply=item id=ActionSkin?%$ActionSkin
This array is used to override the current skin when performing a given action. The most common use is to set $ActionSkin['print']='foo' to use the 'foo' skin when printing, regardless of what the $Skin variable is set to.
%apply=item id=WikiTitle?%$WikiTitle
A variable which contains the Wiki title as displayed by the browser
%apply=item id=EnablePageTitlePriority%$EnablePageTitlePriority
A variable defining how to treat multiple (:title ...:) page directives (added in PmWiki 2.2.9).
$EnablePageTitlePriority = 0; # PmWiki default, last encountered title wins (the title may be changed from included pages or GroupFooter).
$EnablePageTitlePriority = 1; # First title wins; if a title is defined in the page, directives from included pages cannot change it.
%apply=item id=EnableDiffInline?%$EnableDiffInline
If set to 0, this variable switches off the word-level highlighting on the markup in the page history.
$EnableDiffInline = 0; # Disable colors, show plain text differences
%apply=item id=HTMLStylesFmt?%$HTMLStylesFmt
An array of CSS statements to be included in the page's output along with other HTML headers. This array provides an easy place for scripts to add custom CSS statements.
%apply=item id=HTMLHeaderFmt?%$HTMLHeaderFmt
An array of HTML text to be included in the page's <head> section, at the point where the skin template specifies a <!--HTMLHeader--> directive. This array provides an easy place for scripts to add custom HTML headers.
For example, if you want to specify a logo for all the pages of your wiki (a png image for Firefox (and others...), an ico for Internet Explorer):
 
$HTMLHeaderFmt['logo'] =
  '<link href="http://path/to/logo.png" type="image/png" rel="icon" />
  <link href="http://path/to/logo.ico" type="image/x-icon" rel="shortcut icon" />';
Another example, if you want to get the rss notification on some browsers (the rss icon in firefox for instance):
 
$HTMLHeaderFmt['rss'] =
  '<link rel="alternate" type="application/rss+xml" title="Rss All recent Changes" 
     href="$ScriptUrl/Site/AllRecentChanges?action=rss" />';
%apply=item id=HTMLFooterFmt?%$HTMLFooterFmt
Like $HTMLHeaderFmt above, this contains an array of HTML text to be included near the end of an HTML document, at the point where the skin template specifies a <!--HTMLFooter--> directive (usually just before a closing </body> tag). Primarily used by scripts to add custom HTML output after the body of the page output.
%apply=item id=MetaRobots?%$MetaRobots
Sets the value of the <meta name='robots' ... /> tag generated by PmWiki to control search engine robots accessing the site. PmWiki's default setting tells robots to not index anything but the normal page view, and to not index pages in the PmWiki wiki group. Explicitly setting $MetaRobots overrides this default.
        # never index this site
        $MetaRobots = 'noindex,nofollow';
        # disable the robots tag entirely
        $MetaRobots = '';
%apply=item id=MessagesFmt?%$MessagesFmt
An array of HTML text to be displayed at the point of any (:messages:) markup. Commonly used for displaying messages with respect to editing pages.
%apply=item id=RecentChangesFmt?%$RecentChangesFmt
An array specifying the format of the RecentChanges listing.
The key of the array specifies the page where changes will be logged, as in
$RecentChangesFmt['$SiteGroup.AllRecentChanges']
The value of the array specifies the format in which the changes will be logged, as in
'* [[{$Group}.{$Name}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]'
Note the two consecutive spaces before the three dots (. . .). The two spaces separate two parts of the format: the first part doesn't change (e.g. a link to the changed page) and the second part does change (e.g. the date and author of the change). Upon saving a page, PmWiki removes a line that matches the first part and adds a line with the current format before the first line with 2 spaces. This way, any line without two consecutive spaces stays at the top of the recent changes page.
You can use and adapt the following to change the format (put it in config.php):
$RecentChangesFmt['$SiteGroup.AllRecentChanges'] = 
  '* [[{$Group}.{$Name}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]';
$RecentChangesFmt['$Group.RecentChanges'] =
  '* [[{$Group}/{$Name}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]';
Note that changes made to the format will only affect new edits. In other words, you will need to edit a page for your new format to be visible. Note also that you need to have two spaces between the page name and the other information about the edit.
Also note that this variable has other uses, such as not reporting at all to RecentChanges and AllRecentChanges? as found here PmWiki Questions.
%apply=item id=RecentUploadsFmt?%$RecentUploadsFmt
An array specifying the format for uploaded files at the RecentChanges listing. It is similar to $RecentChangesFmt. If enabled, newly uploaded files will be logged to the RecentChanges pages. Default is disabled. See Cookbook:RecentUploadsLog for more information.
%apply=item id=DraftRecentChangesFmt?%$DraftRecentChangesFmt
An array specifying the format of the RecentChanges listing when saving Draft pages.
$RecentChangesFmt is set to $DraftRecentChangesFmt when a Draft page is saved. For example, you could save drafts in a separate Recent Draft Changes page and not list in the normal group's Recent Changes page:
$DraftRecentChangesFmt['$Group.RecentDraftChanges'] =
  '* [[{$Group}/{$Name}]]  . . . $CurrentTime $[by] $AuthorLink: [=$ChangeSummary=]';
$DraftRecentChangesFmt['$Group.RecentChanges'] = '';
%apply=item id=RCLinesMax?%$RCLinesMax
The maximum number of lines to be stored in RecentChanges pages. The default is zero, meaning "no limit".
        $RCLinesMax = 1000;       # maintain at most 1000 recent changes
%apply=item id=PageRedirectFmt?%$PageRedirectFmt
The text to be used when a page is redirected via the (:redirect:) markup.
$PageRedirectFmt = '<p><i>redirected from $FullName</p>';
$PageRedirectFmt = '';
For display options, see also the FAQ on PageDirectives.
%apply=item id=WikiStyle%$WikiStyle
An array which contains the predefined WikiStyles which can be used on a textpage.
See: PmWiki.CustomWikiStyles
%apply=item id=WikiStyleApply?%$WikiStyleApply
An array which defines the scope of wiki styling per HTML element. Default settings are:
'item' => 'li|dt',
'list' => 'ul|ol|dl',
'div' => 'div',
'pre' => 'pre',
'img' => 'img',
'block' => 'p(?!\\sclass=)|div|ul|ol|dl|li|dt|pre|h[1-6]',
'p' => 'p(?!\\sclass=)'
This defines that we can apply wiki styling on:
  • LI elements using the item keyword
  • UL, OL, DL elements using the list keyword
  • etc.
An example of applying scope to an LI element is below. For more information refer to WikiStyle scopes.
* %apply=item red%Here is a red styled list item
* This item would not be styled.
  • Here is a red styled list item
  • This item would not be styled.
You can add additional HTML elements to $WikiStyleApply to apply wiki styles to other HTML elements. For example to allow styling on table rows, or anchor tags.
%apply=item id=MaxIncludes?%$MaxIncludes
Controls the number of times that pages can be included via the (:include:) and other directives, used to control recursion and otherwise pose a sanity check on page contents. $MaxIncludes defaults to 50, but can be set to any value by the wiki administrator.
        $MaxIncludes = 50;            # default
        $MaxIncludes = 1000;          # allow lots of includes
        $MaxIncludes = 0;             # turn off includes
$Skin
Lists the name(s) of skins to load, unless overridden by $ActionSkin. Normally $Skin contains a single string which is a the name of a skin directory, but it may also be an array of names, in which case the first skin found from the list is used.
%apply=item id=SkinDirUrl?%$SkinDirUrl
Set by scripts/skins.php to be the base url of the current skin's directory (i.e., within a 'pub/skins/' directory). This variable is typically used inside of a skin .tmpl file to provide access to .css files and graphic images associated with the skin.
%apply=item id=SkinLibDirs?%$SkinLibDirs
An array which, given the filesystem path (array key) to a skin (or a directory containing several skins), provides the corresponding URL (array value).
The array key is the directory containing the skin.tmpl and skin.php files, as seen by the PmWiki program. It does not have to be publicly accessible.
The value is the URL (web address) of the directory containing the .css, .gif, and other files which appear in the HTML code sent by PMWiki to the browser. This directory must be publicly accessible.
By default $SkinLibDirs is set to:
$SkinLibDirs = array(
  "./pub/skins/\$Skin" => "$PubDirUrl/skins/\$Skin",
  "$FarmD/pub/skins/\$Skin" => "$FarmPubDirUrl/skins/\$Skin");
Extra details: When PMWiki is searching for a skin it looks for a directory named for the skin in the array index/keys, and if it finds it then it will use the files in that directory and also the files in the matching array value url. The two sides normally point to the same publicly accessible directory, but they do not have to.
%apply=item id=PageLogoUrl?%$PageLogoUrl
is the url that refers to a logo image which most skins display somewhere in the page's header (top left usually).
%apply=item id=EnablePathInfo?%$EnablePathInfo
Changes the handling of the page URL. When set to 1 page URL will be ...wiki.php/Main/Main, when set to 0 (default) it will be ...wiki.php?n=Main.Main.
%apply=item id=EnableFixedUrlRedirect?%$EnableFixedUrlRedirect
When PmWiki is given a partial page name (e.g., just the name of a WikiGroup), it uses $PagePathFmt in order to make a complete page name from the partial one, then issues a "redirect" to the browser to tell it to reload the page with the correct full page name. Setting $EnableFixedUrlRedirect=0; blocks the redirect, so that PmWiki continues processing with the adjusted page name rather than issuing the redirect.
%apply=item id=GroupHeaderFmt?%$GroupHeaderFmt
Defines the markup placed at the top of every page. Default value is:
        $GroupHeaderFmt = '(:include $Group.GroupHeader:)(:nl:)';
%apply=item id=GroupPrintHeaderFmt?%$GroupPrintHeaderFmt
Defines the markup placed at the top of every page when action=print. Default value is:
        SDV($GroupPrintHeaderFmt,'(:include $Group.GroupPrintHeader:)(:nl:)');
%apply=item id=GroupFooterFmt?%$GroupFooterFmt
Defines the markup placed at the bottom of every page. Default value is:
        $GroupFooterFmt = '(:include $Group.GroupFooter:)(:nl:)';
%apply=item id=GroupPrintFooterFmt?%$GroupPrintFooterFmt
Defines the markup placed at the bottom of every page when action=print. Default value is:
        SDV($GroupPrintFooterFmt,'(:nl:)(:include $Group.GroupPrintFooter:)');
%apply=item id=PageNotFoundHeaderFmt?%$PageNotFoundHeaderFmt
Specifies the HTTP header to send when attempting to browse a page that doesn't exist. Some webserver packages (notably Microsoft's "Personal Web Server") require that this variable be changed in order to work.
# default
$PageNotFoundHeaderFmt = 'HTTP/1.1 404 Not Found';
# return all pages as found
$PageNotFoundHeaderFmt = 'HTTP/1.1 200 Ok';
Beware when expecting to return the content of a Group(header|footer) for an non existent page! By default PmWiki returns 404 (because the page does not exist), despite there is some content to show. Firefox shows the content, while Internet Explorer displays its default 404 page. $PageNotFoundHeaderFmt MUST be set to return 200 as described above in order to get the expected behaviour with all browsers.
%apply=item id=HTMLVSpace?%$HTMLVSpace
Setting $HTMLVSpace = ''; in a local customizationfile (e.g., local/config.php) prevents insertion of spacer paragraphs (<p class='vspace'></p>) in generated HTML code. To limit this change to a single skin, place the $HTMLVSpace = ''; statement in a skin.php file, preceded by the statement global $HTMLVSpace;.
%apply=item id=HTMLPNewline?%$HTMLPNewline
This variable allows to enable linebreaks by default, i.e. without having the directive (:linebreaks:) in a page or in a GroupHeader. To enable line breaks, add to config.php such a line:
$HTMLPNewline = '<br/>';
%apply=item id=TableCellAttrFmt?%$TableCellAttrFmt
For Tables, defines the HTML attributes given to each <td> or <th> cell in the output. Can contain references to $TableCellCount which holds the horizontal column number of the current cell.
%apply=item id=TableRowAttrFmt?%$TableRowAttrFmt
For Tables, defines the HTML attributes given to each <tr> element in the output. Can contain references to $TableRowCount to give the absolute row number within the table, or $TableRowIndex to provide a repeating row index from 1 to $TableRowIndexMax.
        # Give each row a unique CSS class based on row number (tr1, tr2, tr3, ... )
        $TableRowAttrFmt = "class='tr\$TableRowCount'";
        # Give each row alternating CSS classes (ti1, ti2, ti1, ti2, ti1, ... )
        $TableRowIndexMax = 2;
        $TableRowAttrFmt = "class='ti\$TableRowIndex'";
%apply=item id=TableRowIndexMax?%$TableRowIndexMax
The maximum value for $TableRowIndex in Tables.
        # Set rows indexes as 1, 2, 3, 1, 2, 3, 1, 2, ...
        $TableRowIndexMax = 3;
$FmtV['$TableCellCount']
PMWiki internal variable - Horizontal column number of the current cell. For use in $TableCellAttrFmt and $TableRowAttrFmt. Administrators can use in $TableCellAttrFmt and/or $TableRowAttrFmt.
        Example: $TableCellAttrFmt = 'class=col\$TableCellCount'; 
$FmtV['$TableRowCount']
PMWiki internal variable - Current row number. Administrators can use in $TableCellAttrFmt and/or $TableRowAttrFmt.
        Example: TableRowAttrFmt = "class='row\$TableRowCount'"; 
$FmtV['$TableRowIndex']
PMWiki internal variable - Row index number derived from $TableRowIndexMax. (1,2,3,1,2,3,...). Administrators can use in $TableCellAttrFmt and/or $TableRowAttrFmt.
        Example: $TableRowAttrFmt = "class='ind\$TableRowIndex'";

See also: Edit Variables


LinkVariables

%apply=item id=EnableLinkPageRelative?%$EnableLinkPageRelative
When enabled, causes PmWiki to use relative urls for page links instead of absolute urls.
        $EnableLinkPageRelative = 1;
%apply=item id=PagePathFmt?%$PagePathFmt
This array lists the order in which PmWiki looks for the page that you most likely are attempting to link to. The default is listed below. Look at Cookbook:PagePaths for some ideas.
        array('{$Group}.$1','$1.$1'.'$1.{$DefaultName}')
%apply=item id=LinkPageExistsFmt?%$LinkPageExistsFmt
The (HTML) string to output for links to already existing wiki pages. Defaults to
        <a class='wikilink' href='\$LinkUrl'>\$LinkText</a>
%apply=item id=LinkPageCreateFmt?%$LinkPageCreateFmt
The (HTML) string to output for links to non-existent wiki pages. The default is to add a '?' after the link text with a link to the page edit/create form. Defaults to
        <a class='createlinktext' href='\$PageUrl?action=edit'>\$LinkText</a>
        <a class='createlink' href='\$PageUrl?action=edit'>?</a>
%apply=item id=LinkPageCreateSpaceFmt?%$LinkPageCreateSpaceFmt
Same as $LinkPageCreateFmt, but used when the link text has a space in it.
%apply=item id=LinkPageSelfFmt?%$LinkPageSelfFmt
The (HTML) string to output for self-referencing links (i.e. links to the page itself). Defaults to
        <a class='selflink' href='\$LinkUrl'>\$LinkText</a>
%apply=item id=UrlLinkFmt?%$UrlLinkFmt
The (HTML) string to output for URL-links that begin with 'http:', 'ftp:', etc. Defaults to
        <a class='urllink' href='\$LinkUrl' title='\$LinkAlt' rel='nofollow'>\$LinkText</a>
%apply=item id=IMapLinkFmt?%$IMapLinkFmt
an array of link formats for various link "schemes". Not set as default.
Examples of custom formats to allow different styling via classes:
Links to http: standard url links:
         $IMapLinkFmt['http:'] = "<a class='httplink urllink' href='\$LinkUrl'>\$LinkText</a>";  
Links to https: secure pages:
         $IMapLinkFmt['https:'] = "<a class='httpslink urllink' href='\$LinkUrl'>\$LinkText</a>";   
Links to PmWiki: InterMap shortcut:
         $IMapLinkFmt['PmWiki:'] = "<a class='pmwikilink urllink' href='\$LinkUrl'>\$LinkText</a>";
%apply=item id=InterMapFiles?%$InterMapFiles
An array consisting a list of files and pages containing InterMap entries to be loaded (see CustomInterMap).
%apply=item id=MakePageNameFunction?%$MakePageNameFunction
Name of a custom function to replace MakePageName(), which converts strings into valid page names.
%apply=item id=MakePageNamePatterns?%$MakePageNamePatterns
$MakePageNamePatterns is an array of regular expression replacements that is used to map the page link in a free link such as [[free link]] into a page name. Currently the default sequence is:
    "/'/" => '',                           # strip single-quotes
    "/[^$PageNameChars]+/" => ' ',         # convert non-alnums to spaces
    "/((^|[^-\\w])\\w)/e" 
      => "strtoupper('$1')",               # initial caps after spaces
    "/ /" => ''                            # strip spaces
Note that if you change $MakePageNamePatterns, the documentation links may break. This can be fixed by re-setting $MakePageNamePatterns to the default in PmWiki?.php.
%apply=item id=WikiWordCountMax?%$WikiWordCountMax
The maximum number of times to convert each WikiWord encountered on a page. Defaults to 1,000,000. Common settings for this variable are zero (disable WikiWord links) and one (convert only the first occurrence of each WikiWord).
        $WikiWordCountMax = 0;     # disable WikiWord links
        $WikiWordCountMax = 1;     # convert only first WikiWord
%apply=item id=WikiWordCount%$WikiWordCount
An array that allows the number of WikiWord conversions to be set on a per-WikiWord basis. The default is to use $WikiWordCountMax unless a value is set in this array. By default PmWiki sets $WikiWordCount['PmWiki']=1 to limit the number of conversions of "PmWiki".
        $WikiWordCount['PhD']=0;     # Don't convert "PhD"
        $WikiWordCount['WikiWord']=5;  # Convert WikiWord 5 times
        # the following lines keep a page from linking to itself
        $title = FmtPageName('$Title_',$pagename);
        $WikiWordCount[$title]=0;   
%apply=item id=EnableRedirectQuiet?%$EnableRedirectQuiet
Enable the quiet=1 parameter for the redirect directive. On publicly edited wikis it is advisable not to enable quiet redirects.
        $EnableRedirectQuiet = 0;     # disable quiet redirects (default)
        $EnableRedirectQuiet = 1;     # enable quiet redirects

OtherVariables

%apply=item id=FmtV?%$FmtV
This variable is an array that is used for string substitutions at the end of a call to FmtPageName(). For each element in the array, the "key" (interpreted as a string) will be replaced by the corresponding "value". The variable is intended to be a place to store substitution variables that have frequently changing values (thus avoiding a rebuild of the variable cache making FmtPageName() faster). Also see $FmtP. Values of $FmtV are set by the internal functions FormatTableRow?, LinkIMap, HandleBrowse?, PreviewPage?, HandleEdit?, PmWikiAuth?, and PasswdVar?, apparently to set values for system generated string substitutions like PageText?.

%apply=item id=FmtP?%$FmtP
This variable is an array that is used for pattern substitutions near the beginning of a call to FmtPageName. For each element in the array, the "key" (interpreted as a pattern) will be replaced by the corresponding value evaluated for the name of the current page. This is for instance used to handle $-substitutions that depend on the pagename passed to FmtPageName(). Also see $FmtV. From robots.php: If $EnableRobotCloakActions is set, then a pattern is added to $FmtP to hide any "?action=" url parameters in page urls generated by PmWiki for actions that robots aren't allowed to access. This can greatly reduce the load on the server by not providing the robot with links to pages that it will be forbidden to index anyway.

%apply=item id=FmtPV?%$FmtPV
This variable is an array that is used for defining Page Variables. New variables can be defined with $FmtPV['$VarName'] = 'variable definition'; which can be used in markup with {$VarName}. Please note that the contents of $FmtPV['$VarName'] are eval()ed to produce the final text for $VarName, so the contents must be a PHP expression which is valid at the time of substitution. In particular, this does not work:
#This doesn't work
$FmtPV['$MyText'] = "This is my text."; # WARNING: Doesn't work!
The problem is that the text This is my text. is not a valid PHP expression. To work it would need to be placed in quotes, so that what actually gets stored in $FmtPV['$MyText'] is "This is my text." which is a valid PHP expression for a text string. Thus the correct way to do this would be with an extra set of quotes:
#This will work
$FmtPV['$MyText'] = '"This is my text."';
This also has implications for how internal PHP or PmWiki variables are accessed. To have the page variable $MyVar produce the contents of the internal variable $myvar, many folks try the following which does not work:
#This doesn't work either!
$myvar = SomeComplexFunction();
$FmtPV['$MyVar'] = $myvar; # WARNING: Doesn't work!
There are several correct ways to do this, depending on whether you need the value of the $myvar variable as it was at the time the $FmtPV entry was created, or at the time that a particular instance of $MyVar is being rendered on a page. For most simple page variables that don't change during the processing of a page its more efficient to set the value when the entry is created:
$myvar = SomeComplexFunction();
$FmtPV['$MyVar'] = "'" . $myvar . "'"; #capture contents of $myvar
NOTE: If $myvar should contain single quotes, the above won't work as is, and you'll need to process the variable to escape any internal quotes.
For more complex cases where an internal variable may have different values at different places in the page (possibly due to the effects of other markup), then you need to make the $FmtPV entry make an explicit reference to the global value of the variable (and the variable had better be global) like this:
global $myvar;
$FmtPV['$MyVar'] = '$GLOBALS["myvar"]';
Finally, there's nothing to stop you from simply having the evaluation of the $FmtPV entry execute a function to determine the replacement text:
# add page variable {$Today}, formats today's date as yyyy-mm-dd
$FmtPV['$Today'] = 'strftime("%Y-%m-%d", time() )';
See Cookbook:MoreCustomPageVariables for more examples of how to use $FmtPV.
%apply=item id=MaxPageTextVars?%$MaxPageTextVars
This variable prevents endless loops in accidental recursive PageTextVariables which could lock down a server. Default is 500 which means that each PageTextVariable? from one page can be displayed up to 500 times in one wiki page.

PagelistVariables

%apply=item id=EnablePageListProtect?%$EnablePageListProtect
When set to 1 (which is the default), causes (:pagelist:) and (:searchresults:) to exclude listing any pages for which the browser does not currently have read authorization. Setting this to zero means that read-protected pages can appear in a listing, but can also speed up searches considerably (because page permissions do not need to be checked).
%apply=item id=SearchPatterns?%$SearchPatterns
An array of page name patterns to be required or excluded from search and pagelist results. In order to be included in a search listing or page listing, a page's name must not match any pattern that is delimited by exclamation points (!) and must match all other patterns. See Cookbook:SearchPatterns.
# Limit all searches to Main group
$SearchPatterns['default'][] = '/^Main\\./';
# Exclude the Main group from search results
$SearchPatterns['default'][] = '!^Main\\.!';
# Exclude RecentChanges pages from search results
$SearchPatterns['default'][] = '!\\.(All)?RecentChanges$!';
# Prevent a page from listing itself in (:pagelist:) or (:searchresults:)
$SearchPatterns['default'][] = FmtPageName('!^$FullName$!', $pagename);
%apply=item id=SearchBoxOpt?%$SearchBoxOpt
For example $SearchBoxOpt ['target'] = '$DefaultGroup.Search';
%apply=item id=EnablePageIndex?%$EnablePageIndex
When set to 1, causes PmWiki to maintain a "link and word index" in $PageIndexFile which significantly speeds up categories, backlinks, and searches.
%apply=item id=PageIndexFile?%$PageIndexFile
The location of the "page index" file for (:pagelist:), defaults to $WorkDir/.pageindex.
%apply=item id=PageListCacheDir?%$PageListCacheDir
The name of a writable directory where PmWiki can cache results of (:pagelist:) directives to speed up subsequent displays of the same list. Default is empty, which disables the pagelist cache.
# Enable pagelist caching in work.d/
$PageListCacheDir = 'work.d/';
%apply=item id=PageSearchForm?%$PageSearchForm
The page to be used to format search results for ?action=search (unless the current page has a "searchresults" directive in it). This variable can be an array, in which case the first page found from the array is used.
# Use Search page in current group if it exists, otherwise use Site.Search
$PageSearchForm = array('$Group.Search', '[=$[$SiteGroup/Search]=]');
%apply=item id=FPLTemplatePageFmt?%$FPLTemplatePageFmt
The pages to be searched for a pagelist template specified by a fmt=#xyz parameter. Defaults to searching the current page, Site.LocalTemplates and Site.PageListTemplates.
# PMWiki default setup
global $FPLTemplatePageFmt;
$FPLTemplatePageFmt = array(
    '{$FullName}', 
    '{$SiteGroup}.LocalTemplates', 
    '{$SiteGroup}.PageListTemplates');
It can be customized to look in other pages.
# Search a Group.Templates page as well as the Site templates
global $FPLTemplatePageFmt;
$FPLTemplatePageFmt = array(
    '{$Group}.Templates',
    '{$SiteGroup}.LocalTemplates',
    '{$SiteGroup}.PageListTemplates');
Or declare defaults for the template array:
# Search a Group.Templates page as well as the Site templates
global $FPLTemplatePageFmt;
SDV($FPLTemplatePageFmt, array('{$FullName}',
    '{$Group}.Templates',
    '{$SiteGroup}.LocalTemplates', '{$SiteGroup}.PageListTemplates')
   );
%apply=item id=EnableUndefinedTemplateVars?%$EnableUndefinedTemplateVars
This variable controls how undefined {$$Variable} is processed in includes and PageList templates. If set to 0 (default), undefined {$$Variable}s are removed from the included section or template. If set to 1, undefined {$$Variable}s are displayed as is, with {$$...}. Note that PmWiki versions 2.2.13 and earlier kept unset include/template variables.
$EnableUndefinedTemplateVars = 0; # Delete unset raw template variables
$EnableUndefinedTemplateVars = 1; # Keep and print unset raw template variables

PageListTemplates

Default page list templates

PmWiki's default templates for page lists are in Site.PageListTemplates, which is replaced during upgrades. These default templates can be supplemented or overridden with custom templates stored in other locations.

If the page name is not specified as part of the template name, PmWiki's default configuration looks for templates in the following locations in the following order

  1. the current page
  2. Site.LocalTemplates,
  3. Site.PageListTemplates

Administrators can change those locations by using the $FPLTemplatePageFmt variable.

If the template is on the current page, the current page must be saved for changes involving the template to show up (preview alone will not work).

Custom page list templates

Custom templates are used in the same way as default templates: by referencing the desired format with the fmt=#anchor option. There are several ways to indicate which template to use:

  • fmt=#custom uses the #custom section from the current page, Site.LocalTemplates, or Site.PageListTemplates, (sections are denoted by [[#custom]] anchors.
  • fmt=MyTemplatePage#custom uses a custom format from page MyTemplatePage? from its #custom section.
  • fmt=MyTemplatePage uses a custom format from the entire page MyTemplatePage?.
  • fmt=custom uses custom format which is defined in a cookbook script as custom.

See Cookbook:PagelistTemplateSamples for examples of custom pagelist formats.

Creating page list templates

A pagelist template contains standard pmwiki markup. When creating pagelist output, pmwiki iterates over each page returned from the pagelist and will include the pagelist template markup once for every page in the list.

Special references

During the page list iteration pmwiki sets 3 special page references: =, < and >. These special page references are updated on each pagelist iteration and can be used with the page variables syntax, such as {=$variable}, to define a pagelist template which will format the pagelist output. The meaning of the special references are:

=current pageso {=$Title}displays the title of the current page in the iteration
<previous pageso {<$Group}displays the group of the previous page in the iteration
>next pageso {>$Name}displays the name of the next page in the iteration

The > and < references are most useful to help structure pagelist output before and after the actual pagelist. Some common tests used to structure pagelist output are:

(:template first:) (:if equal {<$Group}:) Iteration is at the beginning of list
(:template last:) (:if equal {>$Group}:) Iteration is at the end of list
(:template first {=$Group}:) (:if ! equal {=$Group} {<$Group}:) Iteration is at the first item in a group
(:template last {=$Group}:) (:if ! equal {=$Group} {>$Group}:) Iteration is at the last item in a group
(:template defaults:) Default options to be used in the pagelist command
(:template each:) Signifies the repeated part

Note: the markup in column 2 is deprecated.

Page list template special markup

Pagelist templates may have special sections

  • (:template first ...:) and (:template ! first ...:)
  • (:template last ...:) and (:template ! last ...:)

to specify output for the first or last page in the list or a group (use !first and !last for output except for the first/last page).

There's also a

  • (:template defaults ...:) to allow a template to specify default options,
  • (:template each ...:) to signify the repeated part, and
  • (:template none:) whose content will appear if no page was found (from version 2.2.5).

These allow Pagelist templates to be easily separated into "sections" that are included or not included in the output based on a variety of conditions. These are intended to be improved versions of the (:if ...:) conditions that have traditionally been used to control pagelist output (however, the (:if:) conditions still work as before).

First, Each, Last, None

The simplest versions of the directives are:

(:template first:)      # markup to display only for first page in list
(:template ! first:)    # markup to display for every page in list but the first
(:template each:)       # markup to display for each page in list
(:template last:)       # markup to display only on last page in list
(:template ! last:)     # markup to display for every page in list but the last
(:template none:)       # markup to display only if no pages were found

So, a pagelist template can specify:

(:template first:)
Pages in the list:
(:template each:)
* [[{=$FullName}]] [-{{=$FullName}$:Summary}-]
(:template last:)
Displayed {$$PageCount} pages.

In addition, the "first" and "last" options can have control break arguments that identify markup to be displayed on the first or last page within a particular control section. For example, to specify markup to be displayed upon reaching the first or last page of a group, one can use

(:template first {=$Group}:)
(:template last {=$Group}:)

Thus, instead of writing control breaks using directives, as in

(:if ! equal {<$Group} {=$Group}:)
Group: {=$Group}
(:ifend:)
* [[{=$FullName}]]

one can now write

(:template first {=$Group}:)
Group: {=$Group}
(:template each:)
* [[{=$FullName}]]

Page text variables and page variables can also be used, for example

(:template default $:Maintainer=- order=$:Maintainer,name:)
(:template first {=$:Maintainer}:)

Default options

In addition, a template may specify default options to be used in the pagelist command. For example, a pagelist template to display a list of pages by their titles (and sorted by title) might use:

[[#bytitle]]
(:template defaults order=title:)
* [[{=$FullName}|+]]
[[#bytitleend]]

Then an author could write (:pagelist fmt=#bytitle:) and the pages would automatically be sorted by title without having to specify an additional "order=title" option to the (:pagelist:) directive.

To specify multiple parameters to an option enclose the parameters in double quotes, eg to sort by a page text variable and then the page name

(:template defaults order="$:Database,name" :)

Examples

(:template defaults ... :)
default options for pagelists using this template
(:template each:)
markup for each page in the pagelist
(:template first:)
markup output only for the first page in the pagelist
(:template last:)
markup output only for the last page in the pagelist
(:template first {=$Group}:)
markup output only for a page where the value of {=$Group} has just changed
(:template last {=$Group}:)
markup output only for a page where the value of {=$Group} will change with the next page

So, we have:

[[#template]]
(:template defaults order=name:)
(:template first:)
Pages ordered by group
(:template first {=$Group}:)

Pages in group [[{=$Group}/]]
(:template each:)
* [[{=$FullName}]]
(:template last {=$Group}:)
   {=$Group} contains {$$GroupPageCount} pages.
(:template last:)
   {$$PageCount} pages total.
[[#templateend]] 

Page list template additional page variables

Additional Page Variables that are only available during pagelist are:

{$$PageCount}       The current page count of this iteration
{$$GroupCount}      The current group count of this iteration
{$$GroupPageCount}  The current page count within the current group of this iteration 
{$$option}          The argument option values from (:pagelist:)

Use of {$$option}: For example {$$trail} returns the page name entered in the trail= option of the pagelist directive. You can make up custom "options" with no other purpose than being displayed in the pagelist.

Redirect

To enable searches that return only one page to automatically redirect to that page add the following to a pagelist template where the "jump to a page" functionality is desired:

(:template last:)
(:if equal {$$PageCount} 1:)(:redirect {=$FullName}:)(:ifend:)

Closure of markup

Any open tables, divs, or other structures inside of (:pagelist:) are, by default, automatically closed at the end of the pagelist command. In other words, (:pagelist:) acts like its own complete page, as opposed to generating markup that is then inserted into the enclosing page.

For example a table generated by the (:cell:) directive in the first (:pagelist:) command is automatically closed at the end of the pagelist. The (:cell:) in the second (:pagelist:) command then starts a new table.

Note that the (:table:) directive doesn't actually start a new table, it's the (:cell:) or (:cellnr:) directive that does it. All that the (:table:) directive does is set attributes for any tables that follow.

Usage

It is advisable to not modify the page Site.PageListTemplates directly so that you will still benefit from upgrades. Instead, modify your Site.LocalTemplates page (which is not part of the PmWiki distribution). Cookbook:PagelistTemplateSamples has many examples of custom pagelist formats.

Other recipes

In addition, the Cookbook has other recipes for special fmt= options, including fmt=dictindex (alphabetical index) and fmt=forum (forum postings).


PathVariables

When dealing with file or path variables, one has to recognize the difference between working with URLs? and files on disk. For example:

  • The include() statements are used to include other files (on disk) into the currently running PmWiki script. Thus they require paths on the server's filesystem.
  • The $ScriptUrl and $PubDirUrl variables are used to tell a browser, connecting via the webserver, how to execute the pmwiki script ($ScriptUrl) and the base url for getting files from PmWiki's pub/ directory ($PubDirUrl).

Note that a browser needs a URL (http://example.com/pmwiki/pub) while an include statement requires a server file path ($FarmD/scripts/something.php).

%apply=item id=FarmD?%$FarmD
The directory on the server where the farm is located (i.e., the directory containing the farm's copy of pmwiki.php and the scripts/ directory). This directory is automatically determined by pmwiki.php when it runs, and can be used to distinguish the farm's cookbook/ and pub/ subdirectories from a field's subdirectories.
%apply=item id=FarmPubDirUrl?%$FarmPubDirUrl
is the url that refers to the pub directory for an entire farm. It defaults to the same value as $PubDirUrl.
%apply=item id=PageCSSListFmt?%$PageCSSListFmt
is an associative array which PmWiki uses to find any local css configuration files. It consists of a set of (key,value) pairs that point to the same file. The key is a possible path to a file on disk holding the css data, while the value is the coresponding URL for that same file. They keys are tested in turn, and for each named file that exists, the browser is instructed to load the corresponding URL. This allows for PMWiki to only load the css file if it exists. (Why see if a CSS exists?) The default value for this variable is:
$PageCSSListFmt = array(
  'pub/css/local.css' => '$PubDirUrl/css/local.css',
  'pub/css/{$Group}.css' => '$PubDirUrl/css/{$Group}.css',
  'pub/css/{$FullName}.css' => '$PubDirUrl/css/{$FullName}.css');
Note that the default (as of version pmwiki-2.1.beta26) makes no reference to $FarmPubDirUrl for css configuration files. If you wish to be able to place css configuration files in both the field's pub directory, and the farm's pub directory, you may want to add these lines to your local/config.php file (as described in Cookbook:SharedPages):
# this adds farm.css to all wikis
$PageCSSListFmt = array(
  '$FarmD/pub/css/farm.css' => '$FarmPubDirUrl/css/farm.css',
  'pub/css/local.css' => '$PubDirUrl/css/local.css',
  'pub/css/$Group.css' => '$PubDirUrl/css/$Group.css',
  'pub/css/$FullName.css' => '$PubDirUrl/css/$FullName.css');
# this enables farm css files in a similar manner to a local wiki
$PageCSSListFmt = array(
  '$FarmD/pub/css/local.css' => '$FarmPubDirUrl/css/local.css',
  '$FarmD/pub/css/$Group.css' => '$FarmPubDirUrl/css/$Group.css',
  '$FarmD/pub/css/$FullName.css' => '$FarmPubDirUrl/css/$FullName.css',
  'pub/css/local.css' => '$PubDirUrl/css/local.css',
  'pub/css/$Group.css' => '$PubDirUrl/css/$Group.css',
  'pub/css/$FullName.css' => '$PubDirUrl/css/$FullName.css');
Note the difference between CSS configuration files and CSS files associated with a skin. Skin files, including associated CSS, can be put in either the farm or the field pub/skins directory, and the program will find them.
%apply=item id=PubDirUrl?%$PubDirUrl
is the URL that refers to the pub directory. That directory contains all the files and subdirectories that must be directly accessible from a browser (e.g. CSS and HTML files). Most prominent here is the skins subdirectory.
The following may work for you[10]
  $ScriptUrl = 'http://'.$_SERVER['HTTP_HOST'].'/pmwiki/pmwiki.php';
  $PubDirUrl = 'http://'.$_SERVER['HTTP_HOST'].'/pmwiki/pub';

https://www.pmwiki.org/wiki

%apply=item id=ScriptUrl?%$ScriptUrl
is the URL that you want people's browsers to use when accessing PmWiki, either as a field or farm. It's used whenever PmWiki needs to generate a link to another PmWiki page or action. PmWiki is usually fairly good about "guessing" the correct value for $ScriptUrl on its own, but sometimes an admin needs to set it explicitly because of URL manipulations by the webserver (such as Cookbook:CleanUrls, mod_rewrite, bizarre PHP configurations, and so on).
%apply=item id=SkinDirUrl?%$SkinDirUrl
Set by scripts/skins.php to be the base url of the current skin's directory (i.e., within a 'pub/skins/' directory). This variable is typically used inside of a skin .tmpl file to provide access to .css files and graphic images associated with the skin.
%apply=item id=WorkDir?%$WorkDir
This variable is a string that gives a local path to a directory where the pmwiki engine can create temporary files etc.
PmWiki needs this for a variety of things, such as building merged edits, caching mailposts entries, keeping track of the last modification time of the site, other types of cache, etc. Do not confuse this variable with $WikiDir; the reason that both $WorkDir and $WikiDir refer by default to the directory wiki.d/ is merely to simplify things for the administrator.
%apply=item id=WikiDir?%$WikiDir
A PageStore-object that refers to how wiki pages are stored.
This can be a simple reference to a directory (typically wiki.d/), or something more advanced such as a MySQL backend or a .dbm-file. Do not confuse this variable with $WorkDir; the reason that both $WorkDir and $WikiDir refer by default to the directory wiki.d/ is merely to simplify things for the administrator.
To store groups of pages in subdirectories add $WikiDir = new PageStore('wiki.d/$Group/$FullName'); to the start of your config file. [11]
%apply=item id=WikiLibDirs?%$WikiLibDirs
An array of PageStore objects that specify where to look for pages.
By default it is set up to look in wiki.d/ and wikilib.d/, but can be changed to look other places.
For example, to exclude the pages that are bundled in the PmWiki distribution, use the line below. (Note that some features such as editing and search rely on having certain pages available, so you may need to copy them to the $WikiDir.)
$WikiLibDirs = array(&$WikiDir); ]@
: :Another example
->[@
 	## for any page name, use the version located in wiki.d if it exists,
 	## use the version located in wikilib2.d, if a wiki.d version does not, and
 	## the version located in wikilib.d, if neither of the above exists
	$WikiLibDirs = array(&$WikiDir,
	    new PageStore('wikilib2.d/{$FullName}'),
	    new PageStore('$FarmD/wikilib.d/{$FullName}'));
See also CustomPageStore.
%apply=item id=LocalDir?%$LocalDir
The filesystem location of the local/ directory, holding local customization and per group customization? files. Typically set in a WikiFarm's farmconfig.php. (Note that farm configuration files always occur in $FarmD/local/farmconfig.php, regardless of any setting for $LocalDir.)

See also


Requirements

Prerequisites for running the PmWiki wiki engine:

  1. PHP 4.3 or later
    • PHP 5 or later is recommended
  2. Some sort of webserver that can run PHP scripts.

PmWiki has been reported to work with the following OS/webserver combinations:

  • Apache 1.3 or 2.0, on roughly anything (Unix, Linux, Windows, and Mac OS/X)
  • lighttpd (1.4.19 php-fastcgi ssl) on Linux
  • nginx (0.8.47) on Windows
  • Microsoft Internet Information Server, on Windows
  • Linux + LiteSpeedWeb Server Standard Edition
  • appWeb (a small, php-enabled webserver) executing on a Linksys NSLU2? Network Storage Link device

PmWiki has been reported not to work on:

  • Mac OS before Mac OS X because there's no PHP available
  • Specific Release Candidate builds of PHP 5.3 for Windows may not work correctly with passwords

The Standalone recipe provides a special, bare-bones webserver application that can be used to run PmWiki in places where another webserver isn't available. PmWiki can also be run from a USB drive.


SpecialCharacters

When creating pages it's common to use commercial trademarks, copyright, umlaut, and other non-keyboard symbols. therefore it's important that you have the means to input these special characters.

ISO Standard codes

PmWiki supports the HTML special character listings by the w3c. W3C Page of Special Character codes ISO standard.

Here are some samples:

&#169; | &#188; | &#189; | &#174; | &#181; | &#168; 

© | ¼ | ½ | ® | µ | ¨

&#198; | 32&#176; | Un&#239;ted St&#228;tes | &#182; | &#165;Yen | PmWiki&#8482;

Æ | 32° | Unïted Stätes | ¶ | ¥Yen | PmWiki

For a nice table of the same codes that show the codes with the output go to the Noble Desktop special character page.

Other ways to do it:

Character Map

Find the "Character Map" utility in your computer's System Tools folder. Click the symbol you're interested in, and note the keystroke information at the bottom of the box. You execute these by holding "Alt" while keying the numbers on the numerical keypad of your keyboard (not the numbers across the top of the board).

&#169; = Alt+0169 = © | &#174; = Alt+0174 = ® | &#176; = Alt+0176 = ° (degrees).

Paste

  • Use Word or another desktop application to create your text with the special characters that you want. Copy and paste the text to the wiki page you're editing or creating.
  • Find an instance of a special character in an online document; copy and paste the character to your wiki page: ©

There's a list of special characters at PmWiki:SpecialCharactersList. There's another illustration at PmWiki:Characters


UploadVariables

See also: Uploads, Uploads admin.

%apply=item id=EnableUpload?%$EnableUpload
The upload.php script is automatically included from stdconfig.php if the $EnableUpload variable is true in config.php. Note that one may still need to set an upload password before users can upload (see UploadsAdmin).
%apply=item id=UploadDir?%$UploadDir
The directory where uploads are to be stored. Defaults to uploads/ in the pmwiki directory, but can be set to any location on the server. This directory must be writable by the webserver process if uploading is to occur.
%apply=item id=UploadUrlFmt?%$UploadUrlFmt
The url of the directory given by $UploadDir. By default, $UploadUrlFmt is derived from $PubDirUrl and $UploadDir.

$IMapLinkFmt['Attach:']

The format of the upload link displayed when an attachment is present. No default is set.
%apply=item id=LinkUploadCreateFmt?%$LinkUploadCreateFmt
The format of the upload link displayed when an attachment not present. Defaults to
      <a class='createlinktext' href='\$LinkUpload'>\$LinkText</a>
<a class='createlink' href='\$LinkUpload'> Δ</a>");
%apply=item id=UploadPrefixFmt?%$UploadPrefixFmt
Sets the prefix for uploaded files to allow attachments to be organized other than by groups. Defaults to '/$Group' (uploads are organized per-group), but can be set to other values for sitewide or per-page attachments.
    $UploadPrefixFmt = '/$Group/$Name';    # per-page attachments
    $UploadPrefixFmt = '';                 # sitewide attachments
It is recommended to have the $UploadPrefixFmt variable defined in config.php, the same for all pages in the wiki, and not in group/page local configuration files. Otherwise you will be unable to link to attachments in other wikigroups.
%apply=item id=EnableDirectDownload?%$EnableDirectDownload
When set to 1 (the default), links to attachments bypass PmWiki and come directly from the webserver. Setting $EnableDirectDownload=0; causes requests for attachments to be obtained via ?action=download. This allows PmWiki to protect attachments using a page's read permissions, but also increases the load on the server. Don't forget to protect your directory /uploads/ with a .htaccess file (Order Deny,Allow / Deny from all).
%apply=item id=EnableUploadGroupAuth?%$EnableUploadGroupAuth
Set $EnableUploadGroupAuth = 1; to authenticate downloads with the group password. This could be used together with $EnableDirectDownload = 0;.
%apply=item id=EnableUploadVersions?%$EnableUploadVersions
When set to 1 (default is 0), uploading a file to a location where a file of the same name already exists causes the old version to be renamed to file.ext,timestamp (instead of being overwritten). timestamp is a Unix-style timestamp.
%apply=item id=EnableUploadOverwrite?%$EnableUploadOverwrite
When set to 1 (the default), determines if overwriting previously uploaded files is allowed.
%apply=item id=UploadNameChars?%$UploadNameChars
The set of characters allowed in upload names. Defaults to "-\w. ", which means alphanumerics, hyphens, underscores, dots, and spaces can be used in upload names, and everything else will be stripped.
$UploadNameChars = "-\\w. !"; # allow dash, letters, digits, dots, spaces and exclamations
$UploadNameChars = "-\\w. \\x80-\\xff"; # allow Unicode
Note: Not all characters can be used in file names, because of various limitations in protocols or operating systems, file systems and server software, or conflict with PmWiki markup:
  • +?:@#%!=/ have special meanings in URL addresses,
  • |\^`[]?:@#%/ may be impossible to save on some systems,
  • <>"|\^`(){}[]#% may conflict with PmWiki markups,
so it is strongly recommended to only enable those if you know what you're doing.
%apply=item id=MakeUploadNamePatterns?%$MakeUploadNamePatterns
An array of regular expression replacements that is used to normalize the filename of an attached file. First, everything but $UploadNameChars will be stripped, then the file extension will be converted to lowercase. Administrators can override these replacements with a custom definition (the full array needs to be defined).
%apply=item id=UploadDirQuota?%$UploadDirQuota
Overall size limit for all uploads.
   $UploadDirQuota = 100*1024;         # limit uploads to 100KiB
   $UploadDirQuota = 1000*1024;        # limit uploads to 1000KiB
   $UploadDirQuota = 1024*1024;        # limit uploads to 1MiB
   $UploadDirQuota = 25*1024*1024;     # limit uploads to 25MiB
   $UploadDirQuota = 2*1024*1024*1024; # limit uploads to 2GiB
%apply=item id=UploadPrefixQuota?%$UploadPrefixQuota
Overall size limit for one directory containing uploads. This directory is usually GroupName? (one for every WikiGroup), or uploads/PageName? (one for every page), depending on the variable $UploadPrefixFmt.
%apply=item id=UploadMaxSize?%$UploadMaxSize
Maximum size for uploading files, 50000 octets (bytes) by default.
%apply=item id=UploadExtSize?%$UploadExtSize
Maximum size per extension, overriding the default in $UploadMaxSize.
   $UploadExtSize['zip'] = 2*1024*1024; # allow up to 2MiB for zip files

WikiAdministrator

A Wiki Administrator is a person (or persons) who installs, configures, and administers a PmWiki system for authors and site visitors. PmWiki has been designed to make the installation and initial setup tasks as easy as possible for people who do not have a lot of knowledge about HTML, PHP, or even web server software. At the same time, PmWiki is designed to be flexible enough so that someone with just a little bit of knowledge about HTML and PHP can customize PmWiki to their specific needs.

See the PmWiki.documentation index for pages about administering PmWiki, administration tasks, security, and PmWiki.audiences for more details of PmWiki's target audiences.


WikiPage

A WikiPage is simply the basic building block of a WikiWikiWeb that contains text and images. See WikiStructures and WikiWikiWeb for more information.

Wiki pages can have an edit template to predefine initial content, see Cookbook:Edit Templates Specify a wiki page or pages to use as a template when a new page is created.

Wiki pages are stored in individual flat files, see Page File Format and Flat File Advantages.


WikiWikiWeb

WikiWikiWeb is an "open-editing" system where the emphasis is on the authoring and collaboration of documents rather than the simple browsing or viewing of them. The name "wiki" is based on the Hawaiian term "wiki wiki", meaning "quick" or "super-fast". The basic concept of a WikiWikiWeb (or "wiki") is that (almost) anyone can edit any page. While at first this sounds like a recipe for complete anarchy, the truth is that sites using this system have developed surprisingly complex and rich communities for online collaboration and communication. Yes, it's possible for someone to go and destroy everything on a page, but it doesn't seem to happen often. And, many systems (including this one) have built-in mechanisms to restore content that has been defaced or destroyed.

The point of the system is to simply make it as quick, easy and rewarding as possible to create or edit online content.

Using any standard Web browser, a person can edit (almost) any page on the system using relatively simple text formatting rules. Creating a link to a new or existing page simply involves putting the word or phrase that will be your link text inside [[double square brackets]] to reference and serve as a title for the target page. In the process of creating the link you're creating the new page, if it doesn't already exist. On some sites (depending on the configuration of PmWiki), a link can also be created by entering a WikiWord -- a word consisting of two or more capitalized words joined together.

It's not necessary to learn all of the formatting rules; others will often come in and reformat things for you. After all, anyone can edit! You can see some of the recent changes that others have posted to this site.

To learn more about adding pages to this Wiki site, see basic editing, then try editing pages in the WikiSandbox.

If you want to learn more about the WikiWikiWeb concept, try some of these Web sites:

Or, send email to Patrick Michaud at pmichaud [snail] pobox [period] com.


WikiWord

A WikiWord is a set of two or more words run together, where the first letter of each word is capitalized. This syntax is also sometimes referred to as "mixed case" or "camel case". Other descriptions of WikiWords are available from Wiki:WikiWord and Wikipedia:WikiWord.

Usage as page titles

WikiWords are used as page titles in a wiki-based system.

Usage as links

In some wikis (depending on the configuration of PmWiki), a valid link can be created by writing it as WikiWord. In such PmWiki installations, WikiWords surrounded by [=...=] or preceded by a backquote (`) are not turned into links:

LikeThis compared to `LikeThis or even [=LikeThis=]

LikeThis? compared to LikeThis or even LikeThis

See Links for information about PmWiki's rules for forming links and forming page titles.

Enabling WikiWord links

WikiWord links are disabled by default since Pmwiki version 2.1 beta2. To enable WikiWord links you need to set in config.php

    $EnableWikiWords = 1;

See also $LinkWikiWords.

WikiWord links to non-existent pages without decoration

If you want to display links to non-existent pages without decoration, place the following lines in pub/css/local.css:

span.wikiword a.createlink { display:none; }
span.wikiword a.createlinktext { border-bottom:none; text-decoration:none; color:inherit; }

Finding WikiWord links

If you upgraded from an earlier version and want to convert WikiWord links to standard links, the following will help to find those WikiWord links easier by highlighting them. Set in config.php:

$HTMLStylesFmt['wikiword'] = "span.wikiword { background:yellow; }";

Disabling certain WikiWords links

The variable $WikiWordCount controls WikiWord conversion on a per word basis.


  0: 00.00 00.00 config start
  1: 00.02 00.01 config end
  2: 00.21 00.21 MarkupToHTML begin
  3: 00.23 00.22 MarkupToHTML begin
  4: 00.23 00.22 ReadApprovedUrls SiteAdmin.ApprovedUrls begin
  5: 00.24 00.23 ReadApprovedUrls SiteAdmin.ApprovedUrls end
  6: 00.24 00.23 MarkupToHTML end
  7: 00.24 00.23 MarkupToHTML begin
  8: 00.24 00.23 MarkupToHTML end
  9: 00.24 00.23 MarkupToHTML begin
 10: 00.25 00.23 MarkupToHTML end
 11: 00.25 00.23 MarkupToHTML begin
 12: 00.25 00.23 MarkupToHTML end
 13: 00.25 00.23 MarkupToHTML begin
 14: 00.25 00.24 MarkupToHTML end
 15: 00.25 00.24 MarkupToHTML begin
 16: 00.25 00.24 MarkupToHTML end
 17: 00.25 00.24 MarkupToHTML begin
 18: 00.25 00.24 MarkupToHTML end
 19: 00.25 00.24 MarkupToHTML begin
 20: 00.26 00.24 MarkupToHTML end
 21: 00.26 00.24 MarkupToHTML begin
 22: 00.26 00.24 MarkupToHTML end
 23: 00.26 00.24 MarkupToHTML begin
 24: 00.26 00.25 MarkupToHTML end
 25: 00.26 00.25 MarkupToHTML begin
 26: 00.26 00.25 MarkupToHTML end
 27: 00.26 00.25 MarkupToHTML begin
 28: 00.26 00.25 MarkupToHTML end
 29: 00.26 00.25 MarkupToHTML begin
 30: 00.26 00.25 MarkupToHTML end
 31: 00.26 00.25 MarkupToHTML begin
 32: 00.26 00.25 MarkupToHTML end
 33: 00.26 00.25 MarkupToHTML begin
 34: 00.26 00.25 MarkupToHTML end
 35: 00.26 00.25 MarkupToHTML begin
 36: 00.26 00.25 MarkupToHTML end
 37: 00.26 00.25 MarkupToHTML begin
 38: 00.27 00.25 MarkupToHTML end
 39: 00.27 00.25 MarkupToHTML begin
 40: 00.27 00.25 MarkupToHTML end
 41: 00.27 00.25 MarkupToHTML begin
 42: 00.27 00.26 MarkupToHTML end
 43: 00.27 00.26 MarkupToHTML begin
 44: 00.27 00.26 MarkupToHTML end
 45: 00.27 00.26 MarkupToHTML begin
 46: 00.27 00.26 MarkupToHTML end
 47: 00.27 00.26 MarkupToHTML begin
 48: 00.27 00.26 MarkupToHTML end
 49: 00.27 00.26 MarkupToHTML begin
 50: 00.27 00.26 MarkupToHTML end
 51: 00.27 00.26 MarkupToHTML begin
 52: 00.27 00.26 MarkupToHTML end
 53: 00.27 00.26 MarkupToHTML begin
 54: 00.27 00.26 MarkupToHTML end
 55: 00.27 00.26 MarkupToHTML begin
 56: 00.27 00.26 MarkupToHTML end
 57: 00.27 00.26 MarkupToHTML begin
 58: 00.27 00.26 MarkupToHTML end
 59: 00.27 00.26 MarkupToHTML begin
 60: 00.28 00.26 MarkupToHTML end
 61: 00.28 00.26 MarkupToHTML begin
 62: 00.28 00.26 MarkupToHTML end
 63: 00.28 00.26 MarkupToHTML begin
 64: 00.28 00.27 MarkupToHTML end
 65: 00.28 00.27 MarkupToHTML begin
 66: 00.28 00.27 MarkupToHTML end
 67: 00.28 00.27 MarkupToHTML begin
 68: 00.28 00.27 MarkupToHTML end
 69: 00.28 00.27 MarkupToHTML begin
 70: 00.28 00.27 MarkupToHTML end
 71: 00.28 00.27 MarkupToHTML begin
 72: 00.28 00.27 MarkupToHTML end
 73: 00.28 00.27 MarkupToHTML begin
 74: 00.29 00.27 MarkupToHTML end
 75: 00.29 00.27 MarkupToHTML begin
 76: 00.29 00.27 MarkupToHTML end
 77: 00.29 00.28 MarkupToHTML begin
 78: 00.29 00.28 MarkupToHTML end
 79: 00.29 00.28 MarkupToHTML begin
 80: 00.29 00.28 MarkupToHTML end
 81: 00.29 00.28 MarkupToHTML begin
 82: 00.29 00.28 MarkupToHTML end
 83: 00.29 00.28 MarkupToHTML begin
 84: 00.29 00.28 MarkupToHTML end
 85: 00.29 00.28 MarkupToHTML begin
 86: 00.29 00.28 MarkupToHTML end
 87: 00.29 00.28 MarkupToHTML begin
 88: 00.29 00.28 MarkupToHTML end
 89: 00.29 00.28 MarkupToHTML begin
 90: 00.29 00.28 MarkupToHTML end
 91: 00.29 00.28 MarkupToHTML begin
 92: 00.30 00.28 MarkupToHTML end
 93: 00.30 00.28 MarkupToHTML begin
 94: 00.30 00.29 MarkupToHTML end
 95: 00.30 00.29 MarkupToHTML begin
 96: 00.30 00.29 MarkupToHTML end
 97: 00.30 00.29 MarkupToHTML begin
 98: 00.30 00.29 MarkupToHTML end
 99: 00.30 00.29 MarkupToHTML begin
100: 00.30 00.29 MarkupToHTML end
101: 00.30 00.29 MarkupToHTML begin
102: 00.30 00.29 MarkupToHTML end
103: 00.30 00.29 MarkupToHTML begin
104: 00.30 00.29 MarkupToHTML end
105: 00.30 00.29 MarkupToHTML begin
106: 00.30 00.29 MarkupToHTML end
107: 00.30 00.29 MarkupToHTML begin
108: 00.31 00.29 MarkupToHTML end
109: 00.31 00.29 MarkupToHTML begin
110: 00.31 00.30 MarkupToHTML end
111: 00.31 00.30 MarkupToHTML begin
112: 00.31 00.30 MarkupToHTML end
113: 00.31 00.30 MarkupToHTML begin
114: 00.31 00.30 MarkupToHTML end
115: 00.31 00.30 MarkupToHTML begin
116: 00.31 00.30 MarkupToHTML end
117: 00.31 00.30 MarkupToHTML begin
118: 00.31 00.30 MarkupToHTML end
119: 00.31 00.30 MarkupToHTML begin
120: 00.31 00.30 MarkupToHTML end
121: 00.31 00.30 MarkupToHTML begin
122: 00.31 00.30 MarkupToHTML end
123: 00.31 00.30 MarkupToHTML begin
124: 00.31 00.30 MarkupToHTML end
125: 00.31 00.30 MarkupToHTML begin
126: 00.32 00.30 MarkupToHTML end
127: 00.32 00.30 MarkupToHTML begin
128: 00.32 00.30 MarkupToHTML end
129: 00.32 00.30 MarkupToHTML begin
130: 00.32 00.31 MarkupToHTML end
131: 00.32 00.31 MarkupToHTML begin
132: 00.32 00.31 MarkupToHTML end
133: 00.32 00.31 MarkupToHTML begin
134: 00.32 00.31 MarkupToHTML end
135: 00.32 00.31 MarkupToHTML begin
136: 00.32 00.31 MarkupToHTML end
137: 00.32 00.31 MarkupToHTML begin
138: 00.32 00.31 MarkupToHTML end
139: 00.32 00.31 MarkupToHTML begin
140: 00.32 00.31 MarkupToHTML end
141: 00.32 00.31 MarkupToHTML begin
142: 00.32 00.31 MarkupToHTML end
143: 00.32 00.31 MarkupToHTML begin
144: 00.33 00.31 MarkupToHTML end
145: 00.33 00.31 MarkupToHTML begin
146: 00.33 00.32 MarkupToHTML end
147: 00.33 00.32 MarkupToHTML begin
148: 00.33 00.32 MarkupToHTML end
149: 00.33 00.32 MarkupToHTML begin
150: 00.33 00.32 MarkupToHTML end
151: 00.33 00.32 MarkupToHTML begin
152: 00.33 00.32 MarkupToHTML end
153: 00.33 00.32 MarkupToHTML begin
154: 00.33 00.32 MarkupToHTML end
155: 00.33 00.32 MarkupToHTML begin
156: 00.33 00.32 MarkupToHTML end
157: 00.33 00.32 MarkupToHTML begin
158: 00.33 00.32 MarkupToHTML end
159: 00.33 00.32 MarkupToHTML begin
160: 00.34 00.32 MarkupToHTML end
161: 00.34 00.32 MarkupToHTML begin
162: 00.34 00.32 MarkupToHTML end
163: 00.34 00.32 MarkupToHTML begin
164: 00.34 00.33 MarkupToHTML end
165: 00.34 00.33 MarkupToHTML begin
166: 00.34 00.33 MarkupToHTML end
167: 00.34 00.33 MarkupToHTML begin
168: 00.34 00.33 MarkupToHTML end
169: 00.34 00.33 MarkupToHTML begin
170: 00.34 00.33 MarkupToHTML end
171: 00.34 00.33 MarkupToHTML begin
172: 00.35 00.33 MarkupToHTML end
173: 00.35 00.33 MarkupToHTML begin
174: 00.35 00.33 MarkupToHTML end
175: 00.35 00.33 MarkupToHTML begin
176: 00.35 00.33 MarkupToHTML end
177: 00.35 00.33 MarkupToHTML begin
178: 00.35 00.34 MarkupToHTML end
179: 00.35 00.34 MarkupToHTML begin
180: 00.35 00.34 MarkupToHTML end
181: 00.35 00.34 MarkupToHTML begin
182: 00.35 00.34 MarkupToHTML end
183: 00.35 00.34 MarkupToHTML begin
184: 00.35 00.34 MarkupToHTML end
185: 00.35 00.34 MarkupToHTML begin
186: 00.35 00.34 MarkupToHTML end
187: 00.35 00.34 MarkupToHTML begin
188: 00.35 00.34 MarkupToHTML end
189: 00.35 00.34 MarkupToHTML begin
190: 00.35 00.34 MarkupToHTML end
191: 00.35 00.34 MarkupToHTML begin
192: 00.36 00.34 MarkupToHTML end
193: 00.36 00.34 MarkupToHTML begin
194: 00.36 00.35 MarkupToHTML end
195: 00.36 00.35 MarkupToHTML begin
196: 00.36 00.35 MarkupToHTML end
197: 00.36 00.35 MarkupToHTML begin
198: 00.36 00.35 MarkupToHTML end
199: 00.36 00.35 MarkupToHTML begin
200: 00.36 00.35 MarkupToHTML end
201: 00.36 00.35 MarkupToHTML begin
202: 00.36 00.35 MarkupToHTML end
203: 00.36 00.35 MarkupToHTML begin
204: 00.36 00.35 MarkupToHTML end
205: 00.36 00.35 MarkupToHTML begin
206: 00.36 00.35 MarkupToHTML end
207: 00.36 00.35 MarkupToHTML begin
208: 00.37 00.35 MarkupToHTML end
209: 00.37 00.35 MarkupToHTML begin
210: 00.37 00.35 MarkupToHTML end
211: 00.37 00.35 MarkupToHTML begin
212: 00.37 00.36 MarkupToHTML end
213: 00.37 00.36 MarkupToHTML begin
214: 00.37 00.36 MarkupToHTML end
215: 00.37 00.36 MarkupToHTML begin
216: 00.37 00.36 MarkupToHTML end
217: 00.37 00.36 MarkupToHTML begin
218: 00.38 00.36 MarkupToHTML end
219: 00.38 00.36 MarkupToHTML begin
220: 00.38 00.36 MarkupToHTML end
221: 00.38 00.36 MarkupToHTML begin
222: 00.38 00.36 MarkupToHTML end
223: 00.38 00.36 MarkupToHTML begin
224: 00.38 00.37 MarkupToHTML end
225: 00.38 00.37 MarkupToHTML begin
226: 00.38 00.37 MarkupToHTML end
227: 00.38 00.37 MarkupToHTML begin
228: 00.39 00.37 MarkupToHTML end
229: 00.39 00.37 MarkupToHTML begin
230: 00.39 00.37 MarkupToHTML end
231: 00.39 00.37 MarkupToHTML begin
232: 00.40 00.38 MarkupToHTML end
233: 00.40 00.38 MarkupToHTML begin
234: 00.40 00.38 MarkupToHTML end
235: 00.40 00.38 MarkupToHTML begin
236: 00.40 00.38 MarkupToHTML end
237: 00.40 00.38 MarkupToHTML begin
238: 00.40 00.38 MarkupToHTML end
239: 00.40 00.38 MarkupToHTML begin
240: 00.42 00.40 MarkupToHTML end
241: 00.42 00.40 MarkupToHTML begin
242: 00.42 00.40 MarkupToHTML end
243: 00.42 00.40 MarkupToHTML begin
244: 00.42 00.40 MarkupToHTML end
245: 00.42 00.40 MarkupToHTML begin
246: 00.42 00.40 MarkupToHTML end
247: 00.42 00.40 MarkupToHTML begin
248: 00.43 00.41 MarkupToHTML end
249: 00.43 00.41 MarkupToHTML begin
250: 00.43 00.41 FPLTemplate: Chain begin
251: 00.43 00.41 FPLTemplate: FPLTemplateLoad
252: 00.43 00.41 FPLTemplate: FPLTemplateDefaults
253: 00.43 00.41 FPLTemplate: FPLTemplatePageList
254: 00.43 00.41 MakePageList pre
255: 00.43 00.41 PageListSources begin
256: 00.43 00.41 PageStore::ls begin wiki.d/{$FullName}
257: 00.44 00.42 PageStore::ls merge wiki.d/{$FullName}
258: 00.44 00.42 PageStore::ls end wiki.d/{$FullName}
259: 00.44 00.42 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
260: 00.44 00.42 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
261: 00.44 00.42 PageStore::ls end $FarmD/wikilib.d/{$FullName}
262: 00.44 00.42 PageListSources end count=314
263: 00.44 00.42 PageListSort pre ret=4 order=$:Summary
264: 00.44 00.42 MakePageList items count=314, filters=
265: 00.44 00.42 MakePageList post count=314, readc=0
266: 00.44 00.42 PageListSort begin
267: 00.60 00.56 PageListSort sort
268: 00.61 00.56 PageListSort end
269: 00.61 00.56 MakePageList end
270: 00.61 00.56 FPLTemplate: FPLTemplatePmWikiOrg
271: 00.61 00.56 MarkupToHTML begin
272: 00.61 00.56 MarkupToHTML end
273: 00.61 00.56 FPLTemplate: FPLTemplateSliceList
274: 00.61 00.56 FPLTemplate: FPLTemplateFormat
275: 00.61 00.56 MarkupToHTML begin
276: 00.61 00.56 MarkupToHTML end
277: 00.61 00.56 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
278: 00.61 00.56 FPLTemplate: Chain end
279: 00.61 00.56 MarkupToHTML end
280: 00.61 00.56 MarkupToHTML begin
281: 00.61 00.56 FPLTemplate: Chain begin
282: 00.61 00.56 FPLTemplate: FPLTemplateLoad
283: 00.62 00.57 FPLTemplate: FPLTemplateDefaults
284: 00.62 00.57 FPLTemplate: FPLTemplatePageList
285: 00.62 00.57 MakePageList pre
286: 00.62 00.57 PageListSources begin
287: 00.62 00.57 PageStore::ls begin wiki.d/{$FullName}
288: 00.62 00.57 PageStore::ls merge wiki.d/{$FullName}
289: 00.62 00.57 PageStore::ls end wiki.d/{$FullName}
290: 00.62 00.57 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
291: 00.62 00.57 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
292: 00.62 00.57 PageStore::ls end $FarmD/wikilib.d/{$FullName}
293: 00.63 00.57 PageListSources end count=314
294: 00.63 00.57 PageListSort pre ret=4 order=-name
295: 00.63 00.57 MakePageList items count=314, filters=PageListVariables
296: 00.63 00.58 MakePageList post count=1, readc=0
297: 00.63 00.58 PageListSort begin
298: 00.63 00.58 PageListSort sort
299: 00.63 00.58 PageListSort end
300: 00.63 00.58 MakePageList end
301: 00.63 00.58 FPLTemplate: FPLTemplatePmWikiOrg
302: 00.63 00.58 MarkupToHTML begin
303: 00.63 00.58 MarkupToHTML end
304: 00.63 00.58 FPLTemplate: FPLTemplateSliceList
305: 00.63 00.58 FPLTemplate: FPLTemplateFormat
306: 00.63 00.58 MarkupToHTML begin
307: 00.63 00.58 MarkupToHTML end
308: 00.63 00.58 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
309: 00.63 00.58 FPLTemplate: Chain end
310: 00.63 00.58 MarkupToHTML end
311: 00.63 00.58 MarkupToHTML begin
312: 00.63 00.58 FPLTemplate: Chain begin
313: 00.63 00.58 FPLTemplate: FPLTemplateLoad
314: 00.64 00.58 FPLTemplate: FPLTemplateDefaults
315: 00.64 00.58 FPLTemplate: FPLTemplatePageList
316: 00.64 00.58 MakePageList pre
317: 00.64 00.58 PageListSources begin
318: 00.64 00.58 PageStore::ls begin wiki.d/{$FullName}
319: 00.64 00.59 PageStore::ls merge wiki.d/{$FullName}
320: 00.64 00.59 PageStore::ls end wiki.d/{$FullName}
321: 00.64 00.59 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
322: 00.64 00.59 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
323: 00.64 00.59 PageStore::ls end $FarmD/wikilib.d/{$FullName}
324: 00.64 00.59 PageListSources end count=314
325: 00.64 00.59 PageListSort pre ret=4 order=-$:Version
326: 00.64 00.59 MakePageList items count=314, filters=PageListVariables
327: 00.65 00.59 MakePageList post count=1, readc=0
328: 00.65 00.59 PageListSort begin
329: 00.65 00.59 PageListSort sort
330: 00.65 00.59 PageListSort end
331: 00.65 00.59 MakePageList end
332: 00.65 00.59 FPLTemplate: FPLTemplatePmWikiOrg
333: 00.65 00.59 MarkupToHTML begin
334: 00.65 00.59 MarkupToHTML end
335: 00.65 00.59 FPLTemplate: FPLTemplateSliceList
336: 00.65 00.59 FPLTemplate: FPLTemplateFormat
337: 00.65 00.59 MarkupToHTML begin
338: 00.65 00.59 MarkupToHTML end
339: 00.65 00.59 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
340: 00.65 00.59 FPLTemplate: Chain end
341: 00.65 00.59 MarkupToHTML end
342: 00.65 00.59 MarkupToHTML begin
343: 00.65 00.59 FPLTemplate: Chain begin
344: 00.65 00.59 FPLTemplate: FPLTemplateLoad
345: 00.65 00.60 FPLTemplate: FPLTemplateDefaults
346: 00.65 00.60 FPLTemplate: FPLTemplatePageList
347: 00.65 00.60 MakePageList pre
348: 00.65 00.60 PageListSources begin
349: 00.65 00.60 PageStore::ls begin wiki.d/{$FullName}
350: 00.66 00.61 PageStore::ls merge wiki.d/{$FullName}
351: 00.66 00.61 PageStore::ls end wiki.d/{$FullName}
352: 00.66 00.61 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
353: 00.66 00.61 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
354: 00.66 00.61 PageStore::ls end $FarmD/wikilib.d/{$FullName}
355: 00.66 00.61 PageListSources end count=314
356: 00.66 00.61 PageListSort pre ret=4 order=name
357: 00.66 00.61 MakePageList items count=314, filters=PageListVariables
358: 00.67 00.61 MakePageList post count=79, readc=0
359: 00.67 00.61 PageListSort begin
360: 00.67 00.61 PageListSort sort
361: 00.67 00.61 PageListSort end
362: 00.67 00.61 MakePageList end
363: 00.67 00.61 FPLTemplate: FPLTemplatePmWikiOrg
364: 00.67 00.61 MarkupToHTML begin
365: 00.67 00.61 MarkupToHTML end
366: 00.67 00.61 FPLTemplate: FPLTemplateSliceList
367: 00.67 00.61 FPLTemplate: FPLTemplateFormat
368: 00.67 00.62 MarkupToHTML begin
369: 00.67 00.62 MarkupToHTML end
370: 00.67 00.62 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
371: 00.67 00.62 FPLTemplate: Chain end
372: 00.67 00.62 MarkupToHTML end
373: 00.67 00.62 MarkupToHTML begin
374: 00.68 00.62 FPLTemplate: Chain begin
375: 00.68 00.62 FPLTemplate: FPLTemplateLoad
376: 00.68 00.62 FPLTemplate: FPLTemplateDefaults
377: 00.68 00.62 FPLTemplate: FPLTemplatePageList
378: 00.68 00.62 MakePageList pre
379: 00.68 00.62 PageListSources begin
380: 00.68 00.62 PageStore::ls begin wiki.d/{$FullName}
381: 00.69 00.63 PageStore::ls merge wiki.d/{$FullName}
382: 00.69 00.63 PageStore::ls end wiki.d/{$FullName}
383: 00.69 00.63 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
384: 00.69 00.63 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
385: 00.69 00.63 PageStore::ls end $FarmD/wikilib.d/{$FullName}
386: 00.69 00.63 PageListSources end count=314
387: 00.69 00.63 PageListSort pre ret=4 order=-$:Audience
388: 00.69 00.63 MakePageList items count=314, filters=
389: 00.69 00.63 MakePageList post count=314, readc=0
390: 00.69 00.63 PageListSort begin
391: 00.69 00.63 PageListSort sort
392: 00.69 00.63 PageListSort end
393: 00.69 00.63 MakePageList end
394: 00.69 00.63 FPLTemplate: FPLTemplatePmWikiOrg
395: 00.69 00.63 MarkupToHTML begin
396: 00.70 00.63 MarkupToHTML end
397: 00.70 00.63 FPLTemplate: FPLTemplateSliceList
398: 00.70 00.63 FPLTemplate: FPLTemplateFormat
399: 00.70 00.64 MarkupToHTML begin
400: 00.71 00.65 MarkupToHTML end
401: 00.71 00.65 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
402: 00.71 00.65 FPLTemplate: Chain end
403: 00.71 00.65 MarkupToHTML end
404: 00.71 00.65 MarkupToHTML begin
405: 00.71 00.65 MarkupToHTML end
406: 00.71 00.65 MarkupToHTML begin
407: 00.72 00.65 MarkupToHTML end
408: 00.72 00.65 MarkupToHTML begin
409: 00.72 00.65 MarkupToHTML end
410: 00.72 00.65 MarkupToHTML begin
411: 00.72 00.66 MarkupToHTML end
412: 00.72 00.66 MarkupToHTML begin
413: 00.72 00.66 MarkupToHTML end
414: 00.72 00.66 MarkupToHTML begin
415: 00.72 00.66 MarkupToHTML end
416: 00.72 00.66 MarkupToHTML begin
417: 00.72 00.66 MarkupToHTML end
418: 00.72 00.66 MarkupToHTML begin
419: 00.72 00.66 MarkupToHTML end
420: 00.72 00.66 MarkupToHTML begin
421: 00.73 00.66 MarkupToHTML end
422: 00.73 00.66 MarkupToHTML begin
423: 00.73 00.66 MarkupToHTML end
424: 00.73 00.66 MarkupToHTML begin
425: 00.73 00.66 MarkupToHTML end
426: 00.73 00.66 MarkupToHTML begin
427: 00.73 00.67 MarkupToHTML end
428: 00.73 00.67 MarkupToHTML begin
429: 00.73 00.67 MarkupToHTML end
430: 00.73 00.67 MarkupToHTML begin
431: 00.73 00.67 MarkupToHTML end
432: 00.73 00.67 MarkupToHTML begin
433: 00.73 00.67 FPLTemplate: Chain begin
434: 00.73 00.67 FPLTemplate: FPLTemplateLoad
435: 00.74 00.67 FPLTemplate: FPLTemplateDefaults
436: 00.74 00.67 FPLTemplate: FPLTemplatePageList
437: 00.74 00.67 MakePageList pre
438: 00.74 00.67 PageListSources begin
439: 00.74 00.67 PageListSources end count=5
440: 00.74 00.67 PageListSort pre ret=0 order=
441: 00.74 00.67 MakePageList items count=5, filters=
442: 00.74 00.67 MakePageList post count=5, readc=0
443: 00.74 00.67 MakePageList end
444: 00.74 00.67 FPLTemplate: FPLTemplatePmWikiOrg
445: 00.74 00.67 MarkupToHTML begin
446: 00.74 00.67 MarkupToHTML end
447: 00.74 00.67 FPLTemplate: FPLTemplateSliceList
448: 00.74 00.67 FPLTemplate: FPLTemplateFormat
449: 00.74 00.68 MarkupToHTML begin
450: 00.75 00.68 MarkupToHTML end
451: 00.75 00.68 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
452: 00.75 00.68 FPLTemplate: Chain end
453: 00.75 00.68 MarkupToHTML end
454: 00.75 00.68 MarkupToHTML begin
455: 00.75 00.68 FPLTemplate: Chain begin
456: 00.75 00.68 FPLTemplate: FPLTemplateLoad
457: 00.75 00.68 FPLTemplate: FPLTemplateDefaults
458: 00.75 00.68 FPLTemplate: FPLTemplatePageList
459: 00.75 00.68 MakePageList pre
460: 00.75 00.68 PageListSources begin
461: 00.75 00.68 PageListSources end count=10
462: 00.75 00.68 PageListSort pre ret=4 order=random
463: 00.75 00.68 MakePageList items count=10, filters=
464: 00.75 00.68 MakePageList post count=10, readc=0
465: 00.75 00.68 PageListSort begin
466: 00.75 00.68 PageListSort sort
467: 00.75 00.68 PageListSort end
468: 00.75 00.68 MakePageList end
469: 00.75 00.68 FPLTemplate: FPLTemplatePmWikiOrg
470: 00.75 00.68 MarkupToHTML begin
471: 00.75 00.68 MarkupToHTML end
472: 00.75 00.68 FPLTemplate: FPLTemplateSliceList
473: 00.75 00.68 FPLTemplate: FPLTemplateFormat
474: 00.75 00.68 MarkupToHTML begin
475: 00.75 00.68 MarkupToHTML end
476: 00.75 00.68 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
477: 00.75 00.68 FPLTemplate: Chain end
478: 00.75 00.68 MarkupToHTML end
479: 00.75 00.68 MarkupToHTML begin
480: 00.77 00.70 MarkupToHTML end
481: 00.77 00.70 MarkupToHTML begin
482: 00.77 00.70 FPLTemplate: Chain begin
483: 00.77 00.70 FPLTemplate: FPLTemplateLoad
484: 00.78 00.71 FPLTemplate: FPLTemplateDefaults
485: 00.78 00.71 FPLTemplate: FPLTemplatePageList
486: 00.78 00.71 MakePageList pre
487: 00.78 00.71 PageListSources begin
488: 00.78 00.71 PageStore::ls begin wiki.d/{$FullName}
489: 00.78 00.71 PageStore::ls merge wiki.d/{$FullName}
490: 00.79 00.71 PageStore::ls end wiki.d/{$FullName}
491: 00.79 00.72 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
492: 00.79 00.72 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
493: 00.79 00.72 PageStore::ls end $FarmD/wikilib.d/{$FullName}
494: 00.80 00.73 PageListSources end count=10330
495: 00.80 00.73 PageListSort pre ret=4 order=name
496: 00.80 00.73 MakePageList items count=10330, filters=
497: 00.81 00.73 MakePageList post count=10330, readc=0
498: 00.81 00.73 PageListSort begin
499: 00.81 00.73 PageListSort sort
500: 00.94 00.86 PageListSort end
501: 00.94 00.86 MakePageList end
502: 00.94 00.87 FPLTemplate: FPLTemplatePmWikiOrg
503: 00.95 00.87 MarkupToHTML begin
504: 00.95 00.87 MarkupToHTML end
505: 00.95 00.87 FPLTemplate: FPLTemplateSliceList
506: 00.95 00.87 FPLTemplate: FPLTemplateFormat
507: 00.95 00.87 MarkupToHTML begin
508: 00.95 00.87 MarkupToHTML end
509: 00.95 00.87 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
510: 00.95 00.87 FPLTemplate: Chain end
511: 00.95 00.87 FPLTemplate: Chain begin
512: 00.95 00.87 FPLTemplate: FPLTemplateLoad
513: 00.95 00.88 FPLTemplate: FPLTemplateDefaults
514: 00.95 00.88 FPLTemplate: FPLTemplatePageList
515: 00.95 00.88 MakePageList pre
516: 00.95 00.88 PageListSources begin
517: 00.95 00.88 PageStore::ls begin wiki.d/{$FullName}
518: 00.96 00.88 PageStore::ls merge wiki.d/{$FullName}
519: 00.96 00.88 PageStore::ls end wiki.d/{$FullName}
520: 00.97 00.89 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
521: 00.97 00.89 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
522: 00.97 00.89 PageStore::ls end $FarmD/wikilib.d/{$FullName}
523: 00.98 00.90 PageListSources end count=10330
524: 00.98 00.90 PageListSort pre ret=4 order=name
525: 00.98 00.90 MakePageList items count=10330, filters=
526: 00.99 00.91 MakePageList post count=10330, readc=0
527: 00.99 00.91 PageListSort begin
528: 00.99 00.91 PageListSort sort
529: 01.14 01.05 PageListSort end
530: 01.14 01.05 MakePageList end
531: 01.14 01.06 FPLTemplate: FPLTemplatePmWikiOrg
532: 01.14 01.06 MarkupToHTML begin
533: 01.14 01.06 MarkupToHTML end
534: 01.14 01.06 FPLTemplate: FPLTemplateSliceList
535: 01.14 01.06 FPLTemplate: FPLTemplateFormat
536: 01.14 01.06 MarkupToHTML begin
537: 01.14 01.06 MarkupToHTML end
538: 01.14 01.06 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
539: 01.14 01.06 FPLTemplate: Chain end
540: 01.15 01.06 FPLTemplate: Chain begin
541: 01.15 01.06 FPLTemplate: FPLTemplateLoad
542: 01.15 01.07 FPLTemplate: FPLTemplateDefaults
543: 01.15 01.07 FPLTemplate: FPLTemplatePageList
544: 01.15 01.07 MakePageList pre
545: 01.15 01.07 PageListSources begin
546: 01.15 01.07 PageStore::ls begin wiki.d/{$FullName}
547: 01.16 01.07 PageStore::ls merge wiki.d/{$FullName}
548: 01.16 01.07 PageStore::ls end wiki.d/{$FullName}
549: 01.17 01.08 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
550: 01.17 01.08 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
551: 01.17 01.08 PageStore::ls end $FarmD/wikilib.d/{$FullName}
552: 01.18 01.09 PageListSources end count=10330
553: 01.18 01.09 PageListSort pre ret=4 order=name
554: 01.18 01.09 MakePageList items count=10330, filters=
555: 01.19 01.10 MakePageList post count=10330, readc=0
556: 01.19 01.10 PageListSort begin
557: 01.19 01.10 PageListSort sort
558: 01.34 01.25 PageListSort end
559: 01.34 01.25 MakePageList end
560: 01.34 01.25 FPLTemplate: FPLTemplatePmWikiOrg
561: 01.34 01.26 MarkupToHTML begin
562: 01.34 01.26 MarkupToHTML end
563: 01.34 01.26 FPLTemplate: FPLTemplateSliceList
564: 01.34 01.26 FPLTemplate: FPLTemplateFormat
565: 01.34 01.26 MarkupToHTML begin
566: 01.34 01.26 MarkupToHTML end
567: 01.34 01.26 FPLTemplate: FPLTemplatePmWikiOrgPostFormat
568: 01.34 01.26 FPLTemplate: Chain end
569: 01.34 01.26 MarkupToHTML end
570: 01.35 01.26 MarkupToHTML begin
571: 01.35 01.26 MarkupToHTML end
572: 01.61 01.52 PageStore::ls begin wiki.d/{$FullName}
573: 01.62 01.52 PageStore::ls merge wiki.d/{$FullName}
574: 01.62 01.53 PageStore::ls end wiki.d/{$FullName}
575: 01.62 01.53 PageStore::ls begin $FarmD/wikilib.d/{$FullName}
576: 01.62 01.53 PageStore::ls merge $FarmD/wikilib.d/{$FullName}
577: 01.62 01.53 PageStore::ls end $FarmD/wikilib.d/{$FullName}
578: 01.66 01.56 MarkupToHTML begin
579: 01.66 01.56 MarkupToHTML end
580: 01.66 01.56 MarkupToHTML begin
581: 01.66 01.56 MarkupToHTML end
582: 04.58 04.45 MarkupToHTML end
583: 04.58 04.46 MarkupToHTML begin
584: 04.59 04.47 MarkupToHTML end
585: 04.60 04.47 MarkupToHTML begin
586: 04.60 04.48 MarkupToHTML end
587: 04.72 04.48 now
Peak memory: 19,878,808 bytes