summary refs log tree commit diff stats
path: root/lib/pure/uri.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/uri.nim')
-rw-r--r--lib/pure/uri.nim56
1 files changed, 36 insertions, 20 deletions
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 9bf25b86b..dd8040928 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -18,14 +18,12 @@ type
     hostname*, port*, path*, query*, anchor*: string
     opaque*: bool
 
-{.deprecated: [TUrl: Url, TUri: Uri].}
-
 {.push warning[deprecated]: off.}
-proc `$`*(url: Url): string {.deprecated.} =
+proc `$`*(url: Url): string {.deprecated: "use Uri instead".} =
   ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   return string(url)
 
-proc `/`*(a, b: Url): Url {.deprecated.} =
+proc `/`*(a, b: Url): Url {.deprecated: "use Uri instead".} =
   ## Joins two URLs together, separating them with / if needed.
   ##
   ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
@@ -40,32 +38,43 @@ proc `/`*(a, b: Url): Url {.deprecated.} =
     urlS.add(bs)
   result = Url(urlS)
 
-proc add*(url: var Url, a: Url) {.deprecated.} =
+proc add*(url: var Url, a: Url) {.deprecated: "use Uri instead".} =
   ## Appends url to url.
   ##
   ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   url = url / a
 {.pop.}
 
-proc encodeUrl*(s: string): string =
-  ## Encodes a value to be HTTP safe: This means that characters in the set
-  ## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
-  ## a space is converted to ``'+'`` and every other character is encoded as
-  ## ``'%xx'`` where ``xx`` denotes its hexadecimal value.
+proc encodeUrl*(s: string, usePlus=true): string =
+  ## Encodes a URL according to RFC3986.
+  ##
+  ## This means that characters in the set
+  ## ``{'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~'}`` are
+  ## carried over to the result.
+  ## All other characters are encoded as ``''%xx'`` where ``xx``
+  ## denotes its hexadecimal value.
+  ##
+  ## As a special rule, when the value of ``usePlus`` is true,
+  ## spaces are encoded as ``'+'`` instead of ``'%20'``.
   result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars
-  for i in 0..s.len-1:
-    case s[i]
-    of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
-    of ' ': add(result, '+')
+  let fromSpace = if usePlus: "+" else: "%20"
+  for c in s:
+    case c
+    of 'a'..'z', 'A'..'Z', '0'..'9', '-', '.', '_', '~': add(result, c)
+    of ' ': add(result, fromSpace)
     else:
       add(result, '%')
-      add(result, toHex(ord(s[i]), 2))
+      add(result, toHex(ord(c), 2))
 
-proc decodeUrl*(s: string): string =
-  ## Decodes a value from its HTTP representation: This means that a ``'+'``
-  ## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
-  ## value) is converted to the character with ordinal number ``xx``, and
+proc decodeUrl*(s: string, decodePlus=true): string =
+  ## Decodes a URL according to RFC3986.
+  ##
+  ## This means that any ``'%xx'`` (where ``xx`` denotes a hexadecimal
+  ## value) are converted to the character with ordinal number ``xx``,
   ## and every other character is carried over.
+  ##
+  ## As a special rule, when the value of ``decodePlus`` is true, ``'+'``
+  ## characters are converted to a space.
   proc handleHexChar(c: char, x: var int) {.inline.} =
     case c
     of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
@@ -84,7 +93,11 @@ proc decodeUrl*(s: string): string =
       handleHexChar(s[i+2], x)
       inc(i, 2)
       result[j] = chr(x)
-    of '+': result[j] = ' '
+    of '+':
+      if decodePlus:
+        result[j] = ' '
+      else:
+        result[j] = s[i]
     else: result[j] = s[i]
     inc(i)
     inc(j)
@@ -370,6 +383,9 @@ when isMainModule:
     const test1 = "abc\L+def xyz"
     doAssert encodeUrl(test1) == "abc%0A%2Bdef+xyz"
     doAssert decodeUrl(encodeUrl(test1)) == test1
+    doAssert encodeUrl(test1, false) == "abc%0A%2Bdef%20xyz"
+    doAssert decodeUrl(encodeUrl(test1, false), false) == test1
+    doAssert decodeUrl(encodeUrl(test1)) == test1
 
   block:
     let str = "http://localhost"
t .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
=========================
  niminst User's manual
=========================

:Author: Andreas Rumpf
:Version: |nimversion|

.. default-role:: code
.. include:: rstcommon.rst
.. contents::

Introduction
============

niminst is a tool to generate an installer for a Nim program. Currently
it can create an installer for Windows
via [Inno Setup](http://www.jrsoftware.org/isinfo.php) as well as
installation/deinstallation scripts for UNIX. Later versions will support
Linux' package management systems.

niminst works by reading a configuration file that contains all the
information that it needs to generate an installer for the different operating
systems.


Configuration file
==================

niminst uses the Nim [parsecfg](parsecfg.html) module to parse the
configuration file. Here's an example of how the syntax looks like:

.. include:: mytest.cfg
     :literal:

The value of a key-value pair can reference user-defined variables via
the `$variable` notation: They can be defined in the command line with the
`--var:name=value`:option: switch. This is useful to not hard-coding the
program's version number into the configuration file, for instance.

It follows a description of each possible section and how it affects the
generated installers.


Project section
---------------
The project section gathers general information about your project. It must
contain the following key-value pairs:

====================   =======================================================
Key                    description
====================   =======================================================
`Name`                 the project's name; this needs to be a single word
`DisplayName`          the project's long name; this can contain spaces. If
                       not specified, this is the same as `Name`.
`Version`              the project's version
`OS`                   the OSes to generate C code for; for example:
                       `"windows;linux;macosx"`
`CPU`                  the CPUs to generate C code for; for example:
                       `"i386;amd64;powerpc"`
`Authors`              the project's authors
`Description`          the project's description
`App`                  the application's type: "Console" or "GUI". If
                       "Console", niminst generates a special batch file
                       for Windows to open up the command-line shell.
`License`              the filename of the application's license
====================   =======================================================


`files` key
-------------

Many sections support the `files` key. Listed filenames
can be separated by semicolon or the `files` key can be repeated. Wildcards
in filenames are supported. If it is a directory name, all files in the
directory are used::

  [Config]
  Files: "configDir"
  Files: "otherconfig/*.conf;otherconfig/*.cfg"


Config section
--------------

The `config` section currently only supports the `files` key. Listed files
will be installed into the OS's configuration directory.


Documentation section
---------------------

The `documentation` section supports the `files` key.
Listed files will be installed into the OS's native documentation directory
(which might be ``$appdir/doc``).

There is a `start` key which determines whether the Windows installer
generates a link to e.g. the ``index.html`` of your documentation.


Other section
-------------

The `other` section currently only supports the `files` key.
Listed files will be installed into the application installation directory
(`$appdir`).


Lib section
-----------

The `lib` section currently only supports the `files` key.
Listed files will be installed into the OS's native library directory
(which might be `$appdir/lib`).


Windows section
---------------

The `windows` section supports the `files` key for Windows-specific files.
Listed files will be installed into the application installation directory
(`$appdir`).

Other possible options are:

====================   =======================================================
Key                    description
====================   =======================================================
`BinPath`              paths to add to the Windows `%PATH%` environment
                       variable. Example: ``BinPath: r"bin;dist\mingw\bin"``
`InnoSetup`            boolean flag whether an Inno Setup installer should be
                       generated for Windows. Example: `InnoSetup: "Yes"`
====================   =======================================================


UnixBin section
---------------

The `UnixBin` section currently only supports the `files` key.
Listed files will be installed into the OS's native bin directory
(e.g. ``/usr/local/bin``). The exact location depends on the
installation path the user specifies when running the `install.sh` script.


Unix section
------------

Possible options are:

====================   =======================================================
Key                    description
====================   =======================================================
`InstallScript`        boolean flag whether an installation shell script
                       should be generated. Example: `InstallScript: "Yes"`
`UninstallScript`      boolean flag whether a de-installation shell script
                       should be generated.
                       Example: `UninstallScript: "Yes"`
====================   =======================================================


InnoSetup section
-----------------

Possible options are:

====================   =======================================================
Key                    description
====================   =======================================================
`path`                 Path to Inno Setup.
                       Example: ``path = r"c:\inno setup 5\iscc.exe"``
`flags`                Flags to pass to Inno Setup.
                       Example: `flags = "/Q"`
====================   =======================================================


C_Compiler section
------------------

Possible options are:

====================   =======================================================
Key                    description
====================   =======================================================
`path`                 Path to the C compiler.
`flags`                Flags to pass to the C Compiler.
                       Example: `flags = "-w"`
====================   =======================================================


Real-world example
==================

The installers for the Nim compiler itself are generated by niminst. Have a
look at its configuration file:

.. include:: ../compiler/installer.ini
     :literal: