Browse Source

init import

Sun, Chaoyang 5 years ago
commit
669feea915
47 changed files with 5187 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 168
    0
      CMakeLists.txt
  3. 674
    0
      GPL.TXT
  4. 101
    0
      config.js
  5. 21
    0
      copyright.txt
  6. BIN
      db/wikipp.db
  7. 81
    0
      media/style-ltr.css
  8. 82
    0
      media/style-rtl.css
  9. 240
    0
      media/style.css
  10. 62
    0
      misk/discount.patch
  11. 305
    0
      po/he.po
  12. 303
    0
      po/pl.po
  13. 307
    0
      po/ru.po
  14. 293
    0
      po/wikipp.pot
  15. 103
    0
      sample_config.js
  16. 46
    0
      sql/mysql.sql
  17. 50
    0
      sql/postgresql.sql
  18. 46
    0
      sql/sqlite3.sql
  19. 11
    0
      src/content.h
  20. 73
    0
      src/diff.h
  21. 114
    0
      src/index.cpp
  22. 22
    0
      src/index.h
  23. 34
    0
      src/index_content.h
  24. 19
    0
      src/main.cpp
  25. 72
    0
      src/markdown.cpp
  26. 33
    0
      src/markdown.h
  27. 143
    0
      src/master.cpp
  28. 33
    0
      src/master.h
  29. 31
    0
      src/master_content.h
  30. 83
    0
      src/migrate.cpp
  31. 180
    0
      src/options.cpp
  32. 41
    0
      src/options.h
  33. 27
    0
      src/options_content.h
  34. 432
    0
      src/page.cpp
  35. 45
    0
      src/page.h
  36. 79
    0
      src/page_content.h
  37. 226
    0
      src/users.cpp
  38. 32
    0
      src/users.h
  39. 42
    0
      src/users_content.h
  40. 58
    0
      src/wiki.cpp
  41. 48
    0
      src/wiki.h
  42. 47
    0
      templates/admin.tmpl
  43. 28
    0
      templates/hist.tmpl
  44. 114
    0
      templates/main.tmpl
  45. 122
    0
      templates/page.tmpl
  46. 44
    0
      templates/toc.tmpl
  47. 71
    0
      wikipp.log

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+build

+ 168
- 0
CMakeLists.txt View File

@@ -0,0 +1,168 @@
1
+cmake_minimum_required(VERSION 2.6)
2
+project(wikipp)
3
+macro (set_rpath target)
4
+	if(UNIX)
5
+		set_target_properties(${target} PROPERTIES
6
+			BUILD_WITH_INSTALL_RPATH TRUE
7
+			INSTALL_RPATH "$ORIGIN;$ORIGIN/../lib;$ORIGIN/.."
8
+			)
9
+	endif()
10
+endmacro()
11
+
12
+include(CPack)
13
+
14
+if(NOT CMAKE_BUILD_TYPE)
15
+  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
16
+        "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
17
+	      FORCE)
18
+endif(NOT CMAKE_BUILD_TYPE)
19
+
20
+option(USE_STATIC_VIEW "Compile view statically into wikipp" OFF)
21
+
22
+if(WIN32 OR CYGWIN)
23
+	add_definitions(-DDLL_EXPORT)
24
+endif()
25
+
26
+
27
+find_library(CPPCMS cppcms)
28
+find_library(BOOSTER booster)
29
+find_library(CPPDB cppdb)
30
+find_library(DISCOUNT markdown)
31
+
32
+find_path(CPPCMS_INC cppcms/application.h)
33
+find_path(BOOSTER_INC booster/shared_ptr.h)
34
+find_path(CPPDB_INC cppdb/frontend.h)
35
+find_path(DISCOUNT_INC mkdio.h)
36
+
37
+if(NOT DISCOUNT_INC OR NOT DISCOUNT)
38
+	message(FATAL 	"-- Discount markdown library was not found, please download it from \n"
39
+			"   http://www.pell.portland.or.us/~orc/Code/discount/ and install it\n"
40
+			"   By extracting it and running ./configure.sh && make CFLAGS=-O2\n")
41
+endif()
42
+
43
+
44
+include_directories(${CPPCMS_INC})
45
+include_directories(${BOOSTER_INC})
46
+include_directories(${CPPDB_INC})
47
+include_directories(${DISCOUNT_INC})
48
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
49
+
50
+find_program(TMPLCC cppcms_tmpl_cc)
51
+find_program(XGETTEXT xgettext)
52
+find_program(MSGFMT msgfmt)
53
+find_program(MSGMERGE msgmerge)
54
+
55
+if(WIN32)
56
+	add_definitions(-DDLL_EXPORT)
57
+endif()
58
+
59
+
60
+set(TEMPLATES 
61
+	${CMAKE_CURRENT_SOURCE_DIR}/templates/main.tmpl
62
+	${CMAKE_CURRENT_SOURCE_DIR}/templates/page.tmpl
63
+	${CMAKE_CURRENT_SOURCE_DIR}/templates/hist.tmpl
64
+	${CMAKE_CURRENT_SOURCE_DIR}/templates/admin.tmpl
65
+	${CMAKE_CURRENT_SOURCE_DIR}/templates/toc.tmpl
66
+)
67
+
68
+set(SRC 
69
+	src/index.cpp
70
+	src/main.cpp
71
+	src/master.cpp
72
+	src/options.cpp
73
+	src/page.cpp
74
+	src/users.cpp
75
+	src/wiki.cpp
76
+	src/markdown.cpp
77
+)
78
+
79
+add_custom_command(
80
+	OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/view.cpp
81
+	COMMAND ${TMPLCC}
82
+		-d wikipp
83
+		-o ${CMAKE_CURRENT_BINARY_DIR}/view.cpp 
84
+		${TEMPLATES}
85
+	DEPENDS ${TEMPLATES})
86
+
87
+
88
+if(USE_STATIC_VIEW)
89
+	add_executable(wikipp ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/view.cpp)
90
+else()
91
+	add_executable(wikipp ${SRC})
92
+	add_library(view SHARED ${CMAKE_CURRENT_BINARY_DIR}/view.cpp)
93
+	set_rpath(view)
94
+	target_link_libraries(view ${BOOSTER} ${CPPCMS})
95
+endif()
96
+set_rpath(wikipp)
97
+
98
+
99
+target_link_libraries(wikipp ${BOOSTER} ${CPPCMS} ${CPPDB} ${DISCOUNT})
100
+
101
+#  Localization
102
+
103
+
104
+set(LOCALES he ru pl)
105
+
106
+set(MO_FILES)
107
+set(UPDATE_PO_LIST)
108
+set(POT_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/po/wikipp.pot")
109
+
110
+add_custom_command(
111
+	OUTPUT ${POT_TEMPLATE}
112
+	COMMAND 
113
+		${XGETTEXT} 
114
+		--keyword=translate:1,1t
115
+		--keyword=translate:1,2,3t
116
+		--keyword=_
117
+		--keyword=N_
118
+		${SRC}
119
+		${CMAKE_CURRENT_BINARY_DIR}/view.cpp
120
+		--output=${POT_TEMPLATE}
121
+	DEPENDS ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/view.cpp
122
+	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
123
+	)
124
+
125
+add_custom_target(update-po)
126
+
127
+foreach(LOCALE ${LOCALES})
128
+	set(MODIR "${CMAKE_CURRENT_BINARY_DIR}/locale/${LOCALE}/LC_MESSAGES")
129
+	file(MAKE_DIRECTORY "${MODIR}")
130
+	set(MOFILE "${MODIR}/wikipp.mo")
131
+	set(POFILE "${CMAKE_CURRENT_SOURCE_DIR}/po/${LOCALE}.po")
132
+	
133
+	add_custom_command(
134
+		OUTPUT ${MOFILE}
135
+		COMMAND ${MSGFMT} ${POFILE} -o ${MOFILE}
136
+		DEPENDS ${POFILE})
137
+	
138
+	add_custom_target(update-po-${LOCALE}
139
+		COMMAND ${MSGMERGE} -U ${POFILE} ${CMAKE_CURRENT_SOURCE_DIR}/po/wikipp.pot 
140
+		DEPENDS ${POT_TEMPLATE}
141
+		)
142
+	add_dependencies(update-po update-po-${LOCALE})
143
+
144
+	set(MO_FILES ${MO_FILES} ${MOFILE})
145
+	set(UPDATE_PO_LIST ${UPDATE_PO_LIST} update-po-${LOCALE})
146
+endforeach()
147
+
148
+add_custom_target(create-po ALL DEPENDS ${MO_FILES})
149
+
150
+add_executable(wikipp_migrate src/migrate.cpp)
151
+set_rpath(wikipp_migrate)
152
+target_link_libraries(wikipp_migrate ${CPPDB})
153
+
154
+
155
+install(TARGETS wikipp wikipp_migrate view
156
+	RUNTIME DESTINATION bin
157
+	LIBRARY DESTINATION lib/wikipp
158
+	ARCHIVE DESTINATION lib/wikipp)
159
+
160
+foreach(STYLE style style-ltr style-rtl) 
161
+	install(FILES media/${STYLE}.css DESTINATION share/wikipp/media)
162
+endforeach()
163
+foreach(LOCALE ${LOCALES})
164
+	install(FILES ${CMAKE_CURRENT_BINARY_DIR}/locale/${LOCALE}/LC_MESSAGES/wikipp.mo 
165
+		DESTINATION share/locale/${LOCALE}/LC_MESSAGES/)
166
+endforeach()
167
+install(FILES sample_config.js DESTINATION share/wikipp)
168
+

+ 674
- 0
GPL.TXT View File

@@ -0,0 +1,674 @@
1
+                    GNU GENERAL PUBLIC LICENSE
2
+                       Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+                            Preamble
9
+
10
+  The GNU General Public License is a free, copyleft license for
11
+software and other kinds of works.
12
+
13
+  The licenses for most software and other practical works are designed
14
+to take away your freedom to share and change the works.  By contrast,
15
+the GNU General Public License is intended to guarantee your freedom to
16
+share and change all versions of a program--to make sure it remains free
17
+software for all its users.  We, the Free Software Foundation, use the
18
+GNU General Public License for most of our software; it applies also to
19
+any other work released this way by its authors.  You can apply it to
20
+your programs, too.
21
+
22
+  When we speak of free software, we are referring to freedom, not
23
+price.  Our General Public Licenses are designed to make sure that you
24
+have the freedom to distribute copies of free software (and charge for
25
+them if you wish), that you receive source code or can get it if you
26
+want it, that you can change the software or use pieces of it in new
27
+free programs, and that you know you can do these things.
28
+
29
+  To protect your rights, we need to prevent others from denying you
30
+these rights or asking you to surrender the rights.  Therefore, you have
31
+certain responsibilities if you distribute copies of the software, or if
32
+you modify it: responsibilities to respect the freedom of others.
33
+
34
+  For example, if you distribute copies of such a program, whether
35
+gratis or for a fee, you must pass on to the recipients the same
36
+freedoms that you received.  You must make sure that they, too, receive
37
+or can get the source code.  And you must show them these terms so they
38
+know their rights.
39
+
40
+  Developers that use the GNU GPL protect your rights with two steps:
41
+(1) assert copyright on the software, and (2) offer you this License
42
+giving you legal permission to copy, distribute and/or modify it.
43
+
44
+  For the developers' and authors' protection, the GPL clearly explains
45
+that there is no warranty for this free software.  For both users' and
46
+authors' sake, the GPL requires that modified versions be marked as
47
+changed, so that their problems will not be attributed erroneously to
48
+authors of previous versions.
49
+
50
+  Some devices are designed to deny users access to install or run
51
+modified versions of the software inside them, although the manufacturer
52
+can do so.  This is fundamentally incompatible with the aim of
53
+protecting users' freedom to change the software.  The systematic
54
+pattern of such abuse occurs in the area of products for individuals to
55
+use, which is precisely where it is most unacceptable.  Therefore, we
56
+have designed this version of the GPL to prohibit the practice for those
57
+products.  If such problems arise substantially in other domains, we
58
+stand ready to extend this provision to those domains in future versions
59
+of the GPL, as needed to protect the freedom of users.
60
+
61
+  Finally, every program is threatened constantly by software patents.
62
+States should not allow patents to restrict development and use of
63
+software on general-purpose computers, but in those that do, we wish to
64
+avoid the special danger that patents applied to a free program could
65
+make it effectively proprietary.  To prevent this, the GPL assures that
66
+patents cannot be used to render the program non-free.
67
+
68
+  The precise terms and conditions for copying, distribution and
69
+modification follow.
70
+
71
+                       TERMS AND CONDITIONS
72
+
73
+  0. Definitions.
74
+
75
+  "This License" refers to version 3 of the GNU General Public License.
76
+
77
+  "Copyright" also means copyright-like laws that apply to other kinds of
78
+works, such as semiconductor masks.
79
+
80
+  "The Program" refers to any copyrightable work licensed under this
81
+License.  Each licensee is addressed as "you".  "Licensees" and
82
+"recipients" may be individuals or organizations.
83
+
84
+  To "modify" a work means to copy from or adapt all or part of the work
85
+in a fashion requiring copyright permission, other than the making of an
86
+exact copy.  The resulting work is called a "modified version" of the
87
+earlier work or a work "based on" the earlier work.
88
+
89
+  A "covered work" means either the unmodified Program or a work based
90
+on the Program.
91
+
92
+  To "propagate" a work means to do anything with it that, without
93
+permission, would make you directly or secondarily liable for
94
+infringement under applicable copyright law, except executing it on a
95
+computer or modifying a private copy.  Propagation includes copying,
96
+distribution (with or without modification), making available to the
97
+public, and in some countries other activities as well.
98
+
99
+  To "convey" a work means any kind of propagation that enables other
100
+parties to make or receive copies.  Mere interaction with a user through
101
+a computer network, with no transfer of a copy, is not conveying.
102
+
103
+  An interactive user interface displays "Appropriate Legal Notices"
104
+to the extent that it includes a convenient and prominently visible
105
+feature that (1) displays an appropriate copyright notice, and (2)
106
+tells the user that there is no warranty for the work (except to the
107
+extent that warranties are provided), that licensees may convey the
108
+work under this License, and how to view a copy of this License.  If
109
+the interface presents a list of user commands or options, such as a
110
+menu, a prominent item in the list meets this criterion.
111
+
112
+  1. Source Code.
113
+
114
+  The "source code" for a work means the preferred form of the work
115
+for making modifications to it.  "Object code" means any non-source
116
+form of a work.
117
+
118
+  A "Standard Interface" means an interface that either is an official
119
+standard defined by a recognized standards body, or, in the case of
120
+interfaces specified for a particular programming language, one that
121
+is widely used among developers working in that language.
122
+
123
+  The "System Libraries" of an executable work include anything, other
124
+than the work as a whole, that (a) is included in the normal form of
125
+packaging a Major Component, but which is not part of that Major
126
+Component, and (b) serves only to enable use of the work with that
127
+Major Component, or to implement a Standard Interface for which an
128
+implementation is available to the public in source code form.  A
129
+"Major Component", in this context, means a major essential component
130
+(kernel, window system, and so on) of the specific operating system
131
+(if any) on which the executable work runs, or a compiler used to
132
+produce the work, or an object code interpreter used to run it.
133
+
134
+  The "Corresponding Source" for a work in object code form means all
135
+the source code needed to generate, install, and (for an executable
136
+work) run the object code and to modify the work, including scripts to
137
+control those activities.  However, it does not include the work's
138
+System Libraries, or general-purpose tools or generally available free
139
+programs which are used unmodified in performing those activities but
140
+which are not part of the work.  For example, Corresponding Source
141
+includes interface definition files associated with source files for
142
+the work, and the source code for shared libraries and dynamically
143
+linked subprograms that the work is specifically designed to require,
144
+such as by intimate data communication or control flow between those
145
+subprograms and other parts of the work.
146
+
147
+  The Corresponding Source need not include anything that users
148
+can regenerate automatically from other parts of the Corresponding
149
+Source.
150
+
151
+  The Corresponding Source for a work in source code form is that
152
+same work.
153
+
154
+  2. Basic Permissions.
155
+
156
+  All rights granted under this License are granted for the term of
157
+copyright on the Program, and are irrevocable provided the stated
158
+conditions are met.  This License explicitly affirms your unlimited
159
+permission to run the unmodified Program.  The output from running a
160
+covered work is covered by this License only if the output, given its
161
+content, constitutes a covered work.  This License acknowledges your
162
+rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+  You may make, run and propagate covered works that you do not
165
+convey, without conditions so long as your license otherwise remains
166
+in force.  You may convey covered works to others for the sole purpose
167
+of having them make modifications exclusively for you, or provide you
168
+with facilities for running those works, provided that you comply with
169
+the terms of this License in conveying all material for which you do
170
+not control copyright.  Those thus making or running the covered works
171
+for you must do so exclusively on your behalf, under your direction
172
+and control, on terms that prohibit them from making any copies of
173
+your copyrighted material outside their relationship with you.
174
+
175
+  Conveying under any other circumstances is permitted solely under
176
+the conditions stated below.  Sublicensing is not allowed; section 10
177
+makes it unnecessary.
178
+
179
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+  No covered work shall be deemed part of an effective technological
182
+measure under any applicable law fulfilling obligations under article
183
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+similar laws prohibiting or restricting circumvention of such
185
+measures.
186
+
187
+  When you convey a covered work, you waive any legal power to forbid
188
+circumvention of technological measures to the extent such circumvention
189
+is effected by exercising rights under this License with respect to
190
+the covered work, and you disclaim any intention to limit operation or
191
+modification of the work as a means of enforcing, against the work's
192
+users, your or third parties' legal rights to forbid circumvention of
193
+technological measures.
194
+
195
+  4. Conveying Verbatim Copies.
196
+
197
+  You may convey verbatim copies of the Program's source code as you
198
+receive it, in any medium, provided that you conspicuously and
199
+appropriately publish on each copy an appropriate copyright notice;
200
+keep intact all notices stating that this License and any
201
+non-permissive terms added in accord with section 7 apply to the code;
202
+keep intact all notices of the absence of any warranty; and give all
203
+recipients a copy of this License along with the Program.
204
+
205
+  You may charge any price or no price for each copy that you convey,
206
+and you may offer support or warranty protection for a fee.
207
+
208
+  5. Conveying Modified Source Versions.
209
+
210
+  You may convey a work based on the Program, or the modifications to
211
+produce it from the Program, in the form of source code under the
212
+terms of section 4, provided that you also meet all of these conditions:
213
+
214
+    a) The work must carry prominent notices stating that you modified
215
+    it, and giving a relevant date.
216
+
217
+    b) The work must carry prominent notices stating that it is
218
+    released under this License and any conditions added under section
219
+    7.  This requirement modifies the requirement in section 4 to
220
+    "keep intact all notices".
221
+
222
+    c) You must license the entire work, as a whole, under this
223
+    License to anyone who comes into possession of a copy.  This
224
+    License will therefore apply, along with any applicable section 7
225
+    additional terms, to the whole of the work, and all its parts,
226
+    regardless of how they are packaged.  This License gives no
227
+    permission to license the work in any other way, but it does not
228
+    invalidate such permission if you have separately received it.
229
+
230
+    d) If the work has interactive user interfaces, each must display
231
+    Appropriate Legal Notices; however, if the Program has interactive
232
+    interfaces that do not display Appropriate Legal Notices, your
233
+    work need not make them do so.
234
+
235
+  A compilation of a covered work with other separate and independent
236
+works, which are not by their nature extensions of the covered work,
237
+and which are not combined with it such as to form a larger program,
238
+in or on a volume of a storage or distribution medium, is called an
239
+"aggregate" if the compilation and its resulting copyright are not
240
+used to limit the access or legal rights of the compilation's users
241
+beyond what the individual works permit.  Inclusion of a covered work
242
+in an aggregate does not cause this License to apply to the other
243
+parts of the aggregate.
244
+
245
+  6. Conveying Non-Source Forms.
246
+
247
+  You may convey a covered work in object code form under the terms
248
+of sections 4 and 5, provided that you also convey the
249
+machine-readable Corresponding Source under the terms of this License,
250
+in one of these ways:
251
+
252
+    a) Convey the object code in, or embodied in, a physical product
253
+    (including a physical distribution medium), accompanied by the
254
+    Corresponding Source fixed on a durable physical medium
255
+    customarily used for software interchange.
256
+
257
+    b) Convey the object code in, or embodied in, a physical product
258
+    (including a physical distribution medium), accompanied by a
259
+    written offer, valid for at least three years and valid for as
260
+    long as you offer spare parts or customer support for that product
261
+    model, to give anyone who possesses the object code either (1) a
262
+    copy of the Corresponding Source for all the software in the
263
+    product that is covered by this License, on a durable physical
264
+    medium customarily used for software interchange, for a price no
265
+    more than your reasonable cost of physically performing this
266
+    conveying of source, or (2) access to copy the
267
+    Corresponding Source from a network server at no charge.
268
+
269
+    c) Convey individual copies of the object code with a copy of the
270
+    written offer to provide the Corresponding Source.  This
271
+    alternative is allowed only occasionally and noncommercially, and
272
+    only if you received the object code with such an offer, in accord
273
+    with subsection 6b.
274
+
275
+    d) Convey the object code by offering access from a designated
276
+    place (gratis or for a charge), and offer equivalent access to the
277
+    Corresponding Source in the same way through the same place at no
278
+    further charge.  You need not require recipients to copy the
279
+    Corresponding Source along with the object code.  If the place to
280
+    copy the object code is a network server, the Corresponding Source
281
+    may be on a different server (operated by you or a third party)
282
+    that supports equivalent copying facilities, provided you maintain
283
+    clear directions next to the object code saying where to find the
284
+    Corresponding Source.  Regardless of what server hosts the
285
+    Corresponding Source, you remain obligated to ensure that it is
286
+    available for as long as needed to satisfy these requirements.
287
+
288
+    e) Convey the object code using peer-to-peer transmission, provided
289
+    you inform other peers where the object code and Corresponding
290
+    Source of the work are being offered to the general public at no
291
+    charge under subsection 6d.
292
+
293
+  A separable portion of the object code, whose source code is excluded
294
+from the Corresponding Source as a System Library, need not be
295
+included in conveying the object code work.
296
+
297
+  A "User Product" is either (1) a "consumer product", which means any
298
+tangible personal property which is normally used for personal, family,
299
+or household purposes, or (2) anything designed or sold for incorporation
300
+into a dwelling.  In determining whether a product is a consumer product,
301
+doubtful cases shall be resolved in favor of coverage.  For a particular
302
+product received by a particular user, "normally used" refers to a
303
+typical or common use of that class of product, regardless of the status
304
+of the particular user or of the way in which the particular user
305
+actually uses, or expects or is expected to use, the product.  A product
306
+is a consumer product regardless of whether the product has substantial
307
+commercial, industrial or non-consumer uses, unless such uses represent
308
+the only significant mode of use of the product.
309
+
310
+  "Installation Information" for a User Product means any methods,
311
+procedures, authorization keys, or other information required to install
312
+and execute modified versions of a covered work in that User Product from
313
+a modified version of its Corresponding Source.  The information must
314
+suffice to ensure that the continued functioning of the modified object
315
+code is in no case prevented or interfered with solely because
316
+modification has been made.
317
+
318
+  If you convey an object code work under this section in, or with, or
319
+specifically for use in, a User Product, and the conveying occurs as
320
+part of a transaction in which the right of possession and use of the
321
+User Product is transferred to the recipient in perpetuity or for a
322
+fixed term (regardless of how the transaction is characterized), the
323
+Corresponding Source conveyed under this section must be accompanied
324
+by the Installation Information.  But this requirement does not apply
325
+if neither you nor any third party retains the ability to install
326
+modified object code on the User Product (for example, the work has
327
+been installed in ROM).
328
+
329
+  The requirement to provide Installation Information does not include a
330
+requirement to continue to provide support service, warranty, or updates
331
+for a work that has been modified or installed by the recipient, or for
332
+the User Product in which it has been modified or installed.  Access to a
333
+network may be denied when the modification itself materially and
334
+adversely affects the operation of the network or violates the rules and
335
+protocols for communication across the network.
336
+
337
+  Corresponding Source conveyed, and Installation Information provided,
338
+in accord with this section must be in a format that is publicly
339
+documented (and with an implementation available to the public in
340
+source code form), and must require no special password or key for
341
+unpacking, reading or copying.
342
+
343
+  7. Additional Terms.
344
+
345
+  "Additional permissions" are terms that supplement the terms of this
346
+License by making exceptions from one or more of its conditions.
347
+Additional permissions that are applicable to the entire Program shall
348
+be treated as though they were included in this License, to the extent
349
+that they are valid under applicable law.  If additional permissions
350
+apply only to part of the Program, that part may be used separately
351
+under those permissions, but the entire Program remains governed by
352
+this License without regard to the additional permissions.
353
+
354
+  When you convey a copy of a covered work, you may at your option
355
+remove any additional permissions from that copy, or from any part of
356
+it.  (Additional permissions may be written to require their own
357
+removal in certain cases when you modify the work.)  You may place
358
+additional permissions on material, added by you to a covered work,
359
+for which you have or can give appropriate copyright permission.
360
+
361
+  Notwithstanding any other provision of this License, for material you
362
+add to a covered work, you may (if authorized by the copyright holders of
363
+that material) supplement the terms of this License with terms:
364
+
365
+    a) Disclaiming warranty or limiting liability differently from the
366
+    terms of sections 15 and 16 of this License; or
367
+
368
+    b) Requiring preservation of specified reasonable legal notices or
369
+    author attributions in that material or in the Appropriate Legal
370
+    Notices displayed by works containing it; or
371
+
372
+    c) Prohibiting misrepresentation of the origin of that material, or
373
+    requiring that modified versions of such material be marked in
374
+    reasonable ways as different from the original version; or
375
+
376
+    d) Limiting the use for publicity purposes of names of licensors or
377
+    authors of the material; or
378
+
379
+    e) Declining to grant rights under trademark law for use of some
380
+    trade names, trademarks, or service marks; or
381
+
382
+    f) Requiring indemnification of licensors and authors of that
383
+    material by anyone who conveys the material (or modified versions of
384
+    it) with contractual assumptions of liability to the recipient, for
385
+    any liability that these contractual assumptions directly impose on
386
+    those licensors and authors.
387
+
388
+  All other non-permissive additional terms are considered "further
389
+restrictions" within the meaning of section 10.  If the Program as you
390
+received it, or any part of it, contains a notice stating that it is
391
+governed by this License along with a term that is a further
392
+restriction, you may remove that term.  If a license document contains
393
+a further restriction but permits relicensing or conveying under this
394
+License, you may add to a covered work material governed by the terms
395
+of that license document, provided that the further restriction does
396
+not survive such relicensing or conveying.
397
+
398
+  If you add terms to a covered work in accord with this section, you
399
+must place, in the relevant source files, a statement of the
400
+additional terms that apply to those files, or a notice indicating
401
+where to find the applicable terms.
402
+
403
+  Additional terms, permissive or non-permissive, may be stated in the
404
+form of a separately written license, or stated as exceptions;
405
+the above requirements apply either way.
406
+
407
+  8. Termination.
408
+
409
+  You may not propagate or modify a covered work except as expressly
410
+provided under this License.  Any attempt otherwise to propagate or
411
+modify it is void, and will automatically terminate your rights under
412
+this License (including any patent licenses granted under the third
413
+paragraph of section 11).
414
+
415
+  However, if you cease all violation of this License, then your
416
+license from a particular copyright holder is reinstated (a)
417
+provisionally, unless and until the copyright holder explicitly and
418
+finally terminates your license, and (b) permanently, if the copyright
419
+holder fails to notify you of the violation by some reasonable means
420
+prior to 60 days after the cessation.
421
+
422
+  Moreover, your license from a particular copyright holder is
423
+reinstated permanently if the copyright holder notifies you of the
424
+violation by some reasonable means, this is the first time you have
425
+received notice of violation of this License (for any work) from that
426
+copyright holder, and you cure the violation prior to 30 days after
427
+your receipt of the notice.
428
+
429
+  Termination of your rights under this section does not terminate the
430
+licenses of parties who have received copies or rights from you under
431
+this License.  If your rights have been terminated and not permanently
432
+reinstated, you do not qualify to receive new licenses for the same
433
+material under section 10.
434
+
435
+  9. Acceptance Not Required for Having Copies.
436
+
437
+  You are not required to accept this License in order to receive or
438
+run a copy of the Program.  Ancillary propagation of a covered work
439
+occurring solely as a consequence of using peer-to-peer transmission
440
+to receive a copy likewise does not require acceptance.  However,
441
+nothing other than this License grants you permission to propagate or
442
+modify any covered work.  These actions infringe copyright if you do
443
+not accept this License.  Therefore, by modifying or propagating a
444
+covered work, you indicate your acceptance of this License to do so.
445
+
446
+  10. Automatic Licensing of Downstream Recipients.
447
+
448
+  Each time you convey a covered work, the recipient automatically
449
+receives a license from the original licensors, to run, modify and
450
+propagate that work, subject to this License.  You are not responsible
451
+for enforcing compliance by third parties with this License.
452
+
453
+  An "entity transaction" is a transaction transferring control of an
454
+organization, or substantially all assets of one, or subdividing an
455
+organization, or merging organizations.  If propagation of a covered
456
+work results from an entity transaction, each party to that
457
+transaction who receives a copy of the work also receives whatever
458
+licenses to the work the party's predecessor in interest had or could
459
+give under the previous paragraph, plus a right to possession of the
460
+Corresponding Source of the work from the predecessor in interest, if
461
+the predecessor has it or can get it with reasonable efforts.
462
+
463
+  You may not impose any further restrictions on the exercise of the
464
+rights granted or affirmed under this License.  For example, you may
465
+not impose a license fee, royalty, or other charge for exercise of
466
+rights granted under this License, and you may not initiate litigation
467
+(including a cross-claim or counterclaim in a lawsuit) alleging that
468
+any patent claim is infringed by making, using, selling, offering for
469
+sale, or importing the Program or any portion of it.
470
+
471
+  11. Patents.
472
+
473
+  A "contributor" is a copyright holder who authorizes use under this
474
+License of the Program or a work on which the Program is based.  The
475
+work thus licensed is called the contributor's "contributor version".
476
+
477
+  A contributor's "essential patent claims" are all patent claims
478
+owned or controlled by the contributor, whether already acquired or
479
+hereafter acquired, that would be infringed by some manner, permitted
480
+by this License, of making, using, or selling its contributor version,
481
+but do not include claims that would be infringed only as a
482
+consequence of further modification of the contributor version.  For
483
+purposes of this definition, "control" includes the right to grant
484
+patent sublicenses in a manner consistent with the requirements of
485
+this License.
486
+
487
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+patent license under the contributor's essential patent claims, to
489
+make, use, sell, offer for sale, import and otherwise run, modify and
490
+propagate the contents of its contributor version.
491
+
492
+  In the following three paragraphs, a "patent license" is any express
493
+agreement or commitment, however denominated, not to enforce a patent
494
+(such as an express permission to practice a patent or covenant not to
495
+sue for patent infringement).  To "grant" such a patent license to a
496
+party means to make such an agreement or commitment not to enforce a
497
+patent against the party.
498
+
499
+  If you convey a covered work, knowingly relying on a patent license,
500
+and the Corresponding Source of the work is not available for anyone
501
+to copy, free of charge and under the terms of this License, through a
502
+publicly available network server or other readily accessible means,
503
+then you must either (1) cause the Corresponding Source to be so
504
+available, or (2) arrange to deprive yourself of the benefit of the
505
+patent license for this particular work, or (3) arrange, in a manner
506
+consistent with the requirements of this License, to extend the patent
507
+license to downstream recipients.  "Knowingly relying" means you have
508
+actual knowledge that, but for the patent license, your conveying the
509
+covered work in a country, or your recipient's use of the covered work
510
+in a country, would infringe one or more identifiable patents in that
511
+country that you have reason to believe are valid.
512
+
513
+  If, pursuant to or in connection with a single transaction or
514
+arrangement, you convey, or propagate by procuring conveyance of, a
515
+covered work, and grant a patent license to some of the parties
516
+receiving the covered work authorizing them to use, propagate, modify
517
+or convey a specific copy of the covered work, then the patent license
518
+you grant is automatically extended to all recipients of the covered
519
+work and works based on it.
520
+
521
+  A patent license is "discriminatory" if it does not include within
522
+the scope of its coverage, prohibits the exercise of, or is
523
+conditioned on the non-exercise of one or more of the rights that are
524
+specifically granted under this License.  You may not convey a covered
525
+work if you are a party to an arrangement with a third party that is
526
+in the business of distributing software, under which you make payment
527
+to the third party based on the extent of your activity of conveying
528
+the work, and under which the third party grants, to any of the
529
+parties who would receive the covered work from you, a discriminatory
530
+patent license (a) in connection with copies of the covered work
531
+conveyed by you (or copies made from those copies), or (b) primarily
532
+for and in connection with specific products or compilations that
533
+contain the covered work, unless you entered into that arrangement,
534
+or that patent license was granted, prior to 28 March 2007.
535
+
536
+  Nothing in this License shall be construed as excluding or limiting
537
+any implied license or other defenses to infringement that may
538
+otherwise be available to you under applicable patent law.
539
+
540
+  12. No Surrender of Others' Freedom.
541
+
542
+  If conditions are imposed on you (whether by court order, agreement or
543
+otherwise) that contradict the conditions of this License, they do not
544
+excuse you from the conditions of this License.  If you cannot convey a
545
+covered work so as to satisfy simultaneously your obligations under this
546
+License and any other pertinent obligations, then as a consequence you may
547
+not convey it at all.  For example, if you agree to terms that obligate you
548
+to collect a royalty for further conveying from those to whom you convey
549
+the Program, the only way you could satisfy both those terms and this
550
+License would be to refrain entirely from conveying the Program.
551
+
552
+  13. Use with the GNU Affero General Public License.
553
+
554
+  Notwithstanding any other provision of this License, you have
555
+permission to link or combine any covered work with a work licensed
556
+under version 3 of the GNU Affero General Public License into a single
557
+combined work, and to convey the resulting work.  The terms of this
558
+License will continue to apply to the part which is the covered work,
559
+but the special requirements of the GNU Affero General Public License,
560
+section 13, concerning interaction through a network will apply to the
561
+combination as such.
562
+
563
+  14. Revised Versions of this License.
564
+
565
+  The Free Software Foundation may publish revised and/or new versions of
566
+the GNU General Public License from time to time.  Such new versions will
567
+be similar in spirit to the present version, but may differ in detail to
568
+address new problems or concerns.
569
+
570
+  Each version is given a distinguishing version number.  If the
571
+Program specifies that a certain numbered version of the GNU General
572
+Public License "or any later version" applies to it, you have the
573
+option of following the terms and conditions either of that numbered
574
+version or of any later version published by the Free Software
575
+Foundation.  If the Program does not specify a version number of the
576
+GNU General Public License, you may choose any version ever published
577
+by the Free Software Foundation.
578
+
579
+  If the Program specifies that a proxy can decide which future
580
+versions of the GNU General Public License can be used, that proxy's
581
+public statement of acceptance of a version permanently authorizes you
582
+to choose that version for the Program.
583
+
584
+  Later license versions may give you additional or different
585
+permissions.  However, no additional obligations are imposed on any
586
+author or copyright holder as a result of your choosing to follow a
587
+later version.
588
+
589
+  15. Disclaimer of Warranty.
590
+
591
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+  16. Limitation of Liability.
601
+
602
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+SUCH DAMAGES.
611
+
612
+  17. Interpretation of Sections 15 and 16.
613
+
614
+  If the disclaimer of warranty and limitation of liability provided
615
+above cannot be given local legal effect according to their terms,
616
+reviewing courts shall apply local law that most closely approximates
617
+an absolute waiver of all civil liability in connection with the
618
+Program, unless a warranty or assumption of liability accompanies a
619
+copy of the Program in return for a fee.
620
+
621
+                     END OF TERMS AND CONDITIONS
622
+
623
+            How to Apply These Terms to Your New Programs
624
+
625
+  If you develop a new program, and you want it to be of the greatest
626
+possible use to the public, the best way to achieve this is to make it
627
+free software which everyone can redistribute and change under these terms.
628
+
629
+  To do so, attach the following notices to the program.  It is safest
630
+to attach them to the start of each source file to most effectively
631
+state the exclusion of warranty; and each file should have at least
632
+the "copyright" line and a pointer to where the full notice is found.
633
+
634
+    <one line to give the program's name and a brief idea of what it does.>
635
+    Copyright (C) <year>  <name of author>
636
+
637
+    This program is free software: you can redistribute it and/or modify
638
+    it under the terms of the GNU General Public License as published by
639
+    the Free Software Foundation, either version 3 of the License, or
640
+    (at your option) any later version.
641
+
642
+    This program is distributed in the hope that it will be useful,
643
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
645
+    GNU General Public License for more details.
646
+
647
+    You should have received a copy of the GNU General Public License
648
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
649
+
650
+Also add information on how to contact you by electronic and paper mail.
651
+
652
+  If the program does terminal interaction, make it output a short
653
+notice like this when it starts in an interactive mode:
654
+
655
+    <program>  Copyright (C) <year>  <name of author>
656
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+    This is free software, and you are welcome to redistribute it
658
+    under certain conditions; type `show c' for details.
659
+
660
+The hypothetical commands `show w' and `show c' should show the appropriate
661
+parts of the General Public License.  Of course, your program's commands
662
+might be different; for a GUI interface, you would use an "about box".
663
+
664
+  You should also get your employer (if you work as a programmer) or school,
665
+if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+For more information on this, and how to apply and follow the GNU GPL, see
667
+<http://www.gnu.org/licenses/>.
668
+
669
+  The GNU General Public License does not permit incorporating your program
670
+into proprietary programs.  If your program is a subroutine library, you
671
+may consider it more useful to permit linking proprietary applications with
672
+the library.  If this is what you want to do, use the GNU Lesser General
673
+Public License instead of this License.  But first, please read
674
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ 101
- 0
config.js View File

@@ -0,0 +1,101 @@
1
+{
2
+	"wikipp" : {
3
+		"script" : "/wikipp",
4
+		"media" :"/media",
5
+		//"syntax_highlighter" : "/media/sh",
6
+		"disable_registration" : false,
7
+
8
+		"languages" : {
9
+			"en" : "en_US.UTF-8" ,
10
+			"he" : "he_IL.UTF-8" ,
11
+			"ru" : "ru_RU.UTF-8" ,
12
+			"pl" : "pl_PL.UTF-8"
13
+		},
14
+
15
+		// Sqlite3 Sample Connection String
16
+		"connection_string" : "sqlite3:db=./db/wikipp.db;@pool_size=16",
17
+		//
18
+		// PostgreSQL Sample Connection String
19
+		// "connection_string" : "postgresql:dbname=wikipp;@pool_size=16",
20
+		//
21
+		// MySQL Sample Connection String
22
+		//
23
+		// "connection_string" : "mysql:database=wikipp;user=root;password=root;@pool_size=16",
24
+		//
25
+		// In Some cases mysql works faster without prepared statements as it uses query cache, so you
26
+		// may change this string to:
27
+		//
28
+		// "connection_string" : "mysql:database=wikipp;user=root;password=root;@pool_size=16;@use_prepared=off",
29
+		//	
30
+	},
31
+	"service" : {
32
+		"api" : "http",
33
+		"port" : 8080,
34
+		// "api" : "fastcgi",
35
+		// "socket" : "/tmp/wikipp.sock"
36
+		// "socket" : "stdin"
37
+	},
38
+	"session" : {
39
+		"expire" : "renew",
40
+		"location" : "client",
41
+		"timeout" : 2592000, // One month 24*3600*30
42
+		"cookies" :  {
43
+			"prefix" : "wikipp"
44
+		},
45
+		"server" : {
46
+			"storage" : "files" 
47
+		},
48
+		"client" : {
49
+			"encryptor" : "aes",
50
+			"key" : "9bc6dbda707cb72ea1205dd5b1c90464"
51
+		}
52
+	},
53
+	"views" : {
54
+		"paths" : [ "./build"] ,
55
+		"skins" : [ "view" ] ,
56
+		//"auto_reload" : true
57
+	},
58
+	"file_server" : {
59
+		"enable": true,
60
+		"doument_root" : "."
61
+	},
62
+	"localization" : {
63
+		// "backend" : "std", you may switch if for performance enhanecements 
64
+		"messages" : { 
65
+			"paths" : [ "./build/locale"],
66
+			"domains" :  [ "wikipp" ]
67
+		},
68
+		"locales" : [ "he_IL.UTF-8" , "en_US.UTF-8", "ru_RU.UTF-8", "pl_PL.UTF-8" ]
69
+	},
70
+	"http" : {
71
+		"script_names" : [ "/wikipp" ]
72
+	},
73
+	"logging" : {
74
+		"level" : "info",
75
+		"syslog" : {
76
+			"enable": true,
77
+			"id" : "WikiPP"
78
+		},
79
+		"file" : {
80
+			"name" : "./wikipp.log",
81
+			"append" : true
82
+		}
83
+	},
84
+	"cache" : {
85
+		"backend" : "thread_shared", 
86
+		"limit" : 100, // items - thread cache
87
+	},
88
+	"security" : {
89
+		"csrf" : { "enable" : true }
90
+		// "multipart_form_data_limit" : 65536, // KB
91
+		// "content_length_limit" : 1024, // KB
92
+		// "uploads_path" : "" // temporary directory
93
+		//
94
+		// You may change to true for debugging only
95
+		// "display_error_message" : false
96
+	}
97
+
98
+}
99
+
100
+
101
+

+ 21
- 0
copyright.txt View File

@@ -0,0 +1,21 @@
1
+    Wikipp - C++ Wiki Engine
2
+
3
+    Copyright (C) 2009-2012  Artyom Beilis <artyomtnk@yahoo.com>
4
+
5
+    This program is free software: you can redistribute it and/or modify
6
+    it under the terms of the GNU General Public License as published by
7
+    the Free Software Foundation, either version 3 of the License, or
8
+    (at your option) any later version.
9
+
10
+    This program is distributed in the hope that it will be useful,
11
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+    GNU General Public License for more details.
14
+
15
+    You should have received a copy of the GNU General Public License
16
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+
18
+    ------------------------------------------------------------------
19
+    Additional exemptions  compiling, linking, and/or using
20
+    OpenSSL and discount markdown library is allowed.
21
+

BIN
db/wikipp.db View File


+ 81
- 0
media/style-ltr.css View File

@@ -0,0 +1,81 @@
1
+
2
+*{
3
+	padding:0;
4
+	margin:0;
5
+}
6
+h1, h2, h3, h4, h5, h6, p, pre, blockquote, label, ul, ol, dl, 
7
+fieldset, address, pre { margin:0.75em 0;}
8
+
9
+li, dd { 
10
+	margin-left:2em;
11
+}
12
+
13
+blockquote, pre {
14
+        margin-left:20px;
15
+        margin-right:20px;
16
+        padding-left:5px;
17
+        border-left: #999999 solid thin;
18
+}
19
+
20
+#sidecontent {
21
+	padding:10px 10px 20px 10px;
22
+	margin:0px 0px 10px 0px;
23
+	float:right;
24
+}
25
+
26
+#maincontent {
27
+	padding:0px 5px 5px 0px;
28
+	float:left;
29
+}
30
+
31
+#copyrightdesign {
32
+	padding:5px 20px 5px 0px;
33
+	float:left;
34
+}
35
+
36
+#footercontact {
37
+	padding:5px 0px 5px 0px;
38
+	float:right;
39
+}
40
+
41
+.published{
42
+        text-align:left;
43
+}
44
+
45
+.nextpage{
46
+        text-align:right;
47
+}
48
+
49
+
50
+#slogan {
51
+	padding:10px 20px 0px 0px;
52
+	margin:0px 0px 0px 0px;
53
+	float:left;
54
+}
55
+
56
+#nav li {
57
+	float: right;
58
+}
59
+
60
+#title {
61
+	padding:0px 0px 0px 0px;
62
+	margin:0px 0px 0px 0px;
63
+	float:left;
64
+}
65
+
66
+#navall { float:right; }
67
+
68
+#nav {
69
+	text-align: right;
70
+	margin: 0px 0px 0px 0px;
71
+	padding: 0px 0px 0px 0px;
72
+}
73
+
74
+#header{
75
+	padding:5px 0px 10px 0px;
76
+	margin:0px 0px 0px 0px;
77
+}
78
+
79
+#langlist {
80
+	text-align: right;
81
+}

+ 82
- 0
media/style-rtl.css View File

@@ -0,0 +1,82 @@
1
+body {direction:rtl}
2
+
3
+
4
+h1, h2, h3, h4, h5, h6, p, pre, blockquote, label, ul, ol, dl, 
5
+fieldset, address, pre { margin-right:0.0em;}
6
+
7
+ul, ol, dl { padding-right:2.5em; }
8
+
9
+blockquote, pre {
10
+        margin-left:20px;
11
+        margin-right:20px;
12
+        padding-right:5px;
13
+        border-right: #999999 solid thin;
14
+}
15
+
16
+
17
+.dp-highlighter { direction:ltr; }
18
+
19
+#sidecontent {
20
+	padding:10px 10px 20px 10px;
21
+	margin:0px 0px 10px 0px;
22
+	float:left;
23
+}
24
+
25
+#maincontent {
26
+	padding:5px 0px 5px 0px;
27
+	float:right;
28
+}
29
+
30
+#copyrightdesign {
31
+	padding:5px 0px 5px 0px;
32
+	float:right;
33
+}
34
+
35
+#footercontact {
36
+	padding:5px 0px 5px 0px;
37
+	float:left;
38
+}
39
+
40
+.published {
41
+        text-align:right;
42
+}
43
+
44
+.nextpage{
45
+        text-align:left;
46
+}
47
+
48
+
49
+#slogan {
50
+	padding:10px 0px 0px 0px;
51
+	margin:0px 0px 0px 0px;
52
+	float:right;
53
+}
54
+
55
+#nav li {
56
+	float: left;
57
+	margin-right:1em;
58
+}
59
+
60
+#title {
61
+	padding:0px 0px 0px 0px;
62
+	margin:0px 0px 0px 0px;
63
+	float:right;
64
+}
65
+
66
+#navall { float:left; }
67
+
68
+
69
+#nav {
70
+	text-align: left;
71
+	margin: 0px 0px 0px 0px;
72
+	padding: 0px 0px 0px 0px;
73
+}
74
+
75
+#header{
76
+	padding:5px 0px 10px 0px;
77
+	margin:0px 0px 0px 0px;
78
+}
79
+
80
+#langlist {
81
+	text-align: left;
82
+}

+ 240
- 0
media/style.css View File

@@ -0,0 +1,240 @@
1
+/***************************************************************************
2
+*                                                                          *
3
+* contented5 - An open source xhtml/css website template by Contented      *
4
+* Designs.  You're free to modify it and use it for any purpose without    *
5
+* cost or obligation. We'd prefer that you leave the link to our website   *
6
+* in the footer but it's not required.                                     *
7
+*                                                                          *
8
+* If you have comments or questions, please contact us at                  *
9
+* http://www.ContentedDesigns.com. Thanks!                                 *
10
+*                                                                          *
11
+* Version: 1.01 (May 17, 2006)                                             *
12
+***************************************************************************/
13
+
14
+#page {
15
+	color: #222222;
16
+	background-color:#FFFFFF;
17
+	font-family: Arial, sans-serif;
18
+	font-size:83%;
19
+	margin:20px auto;
20
+	width:760px;
21
+	padding-left:10px;
22
+	padding-right:10px;
23
+}
24
+
25
+
26
+h1 {font-size:167%; border-bottom: #999999 solid thin;}
27
+
28
+h2 {font-size:139%;}
29
+
30
+h3 {font-size:120%;}
31
+
32
+h4 {font-size:100%;}
33
+
34
+#title { border:none; }
35
+
36
+
37
+a {
38
+	color: #CC0000;
39
+	background-color: #FFFFFF;
40
+	font-weight: normal;
41
+	text-decoration: none;
42
+}
43
+
44
+a:hover {
45
+	color: #CC0000;
46
+	background-color: #FFFFFF;
47
+	font-weight: normal;
48
+	text-decoration: underline;
49
+}
50
+
51
+#contact {
52
+	padding:0px 0px 0px 0px;
53
+	float:right;
54
+}
55
+
56
+#contact a {
57
+	color: #CC0000;
58
+	background-color:#FFFFFF;
59
+	font-weight:bold;
60
+	text-decoration:none;
61
+}
62
+
63
+#contact a:hover {
64
+	color: #CC0000;
65
+	background-color:#FFFFFF;
66
+	text-decoration:underline;
67
+}
68
+
69
+#header {
70
+	clear:both;
71
+	color: #CC0000;
72
+	background-color:#FFFFFF;
73
+}
74
+
75
+
76
+#title {
77
+	color: #CC0000;
78
+	background-color:#FFFFFF;
79
+	font-size:200%;
80
+	font-weight:bold;
81
+	width:90%;
82
+}
83
+
84
+#slogan {
85
+	color:#222222;
86
+	background-color:#FFFFFF;
87
+	font-size:83%;
88
+	font-weight:normal;
89
+	font-style:normal;
90
+	width:90%;
91
+}
92
+
93
+#navall {width:40%;}
94
+#nav {
95
+	line-height:125%;
96
+	height:3em;
97
+	list-style: none;
98
+	text-align: left;
99
+}
100
+
101
+#nav ul {list-style: none; }
102
+
103
+#nav li a {
104
+	display: block;
105
+	font-size: small;
106
+	color: #CC0000;
107
+	background-color:#FFFFFF;
108
+	font-weight: normal;
109
+	text-decoration: none;
110
+}
111
+
112
+#nav li a:hover { 
113
+	border-bottom:3px solid #CC0000;
114
+}
115
+
116
+#nav a.selected { 
117
+	border-bottom:3px solid #CC0000;
118
+}
119
+
120
+
121
+
122
+#path {
123
+	width:760px;
124
+	clear:both;
125
+	float:left;
126
+	font-size:75%;
127
+	font-weight:normal;
128
+	margin:4px 0px 5px 0px;
129
+	border-top:5px solid #222222;
130
+}
131
+
132
+#path a {
133
+	font-weight:normal;
134
+}
135
+
136
+
137
+
138
+#sidecontent a {
139
+	color: #CC0000;
140
+	background-color:#FFFFFF;
141
+}
142
+
143
+#sidecontent h2 { margin:0.75em 0.25em 0.25em 0em;}
144
+
145
+#sidecontent ul { margin:0.25em 0.25em 0.25em 0.25em;}
146
+
147
+#footer {
148
+	height:40px;
149
+	color:#222222;
150
+	background-color:#FFFFFF;
151
+	border-top:5px solid #222222;
152
+	font-size:75%;
153
+	line-height:1.5em;
154
+	width: 760px;
155
+	clear:both;
156
+}
157
+
158
+#footer	a {
159
+	color:#CC0000;
160
+	background-color:#FFFFFF;
161
+	text-decoration: none;
162
+}
163
+
164
+#footer	a:hover {
165
+	color:#CC0000;
166
+	background-color:#FFFFFF;
167
+	font-weight: normal;
168
+	text-decoration: underline;
169
+}
170
+
171
+
172
+
173
+.published, .nextpage, .rsslink {
174
+        font-size:80%;
175
+        font-style:italic;
176
+        margin-top:-10px;
177
+        padding-top:0px;
178
+}
179
+
180
+
181
+
182
+#comments {
183
+        border-top: #999999 solid thin;
184
+} 
185
+
186
+#comments dd {
187
+        margin-left:25px;
188
+        padding-left:5px;
189
+        margin-right:25px;
190
+        padding-right:5px;
191
+}
192
+
193
+#comments textarea {
194
+	width:100%
195
+}
196
+
197
+#footercontact {
198
+	color:#CC0000;
199
+	background-color:#FFFFFF;
200
+}
201
+
202
+#copyrightdesign {
203
+	color:#222222;
204
+	background-color:#FFFFFF;
205
+	width: 580px;
206
+}
207
+
208
+#maincontent {
209
+	font-size:100%;
210
+	margin:0px 0px 0px 0px;
211
+	width:540px;
212
+        text-align:justify;
213
+}
214
+
215
+
216
+#sidecontent {
217
+	font-family:Arial, sans-serif;
218
+	color: #222222;
219
+	background-color:#FFFFFF;
220
+	font-size:75%;
221
+	width:180px;
222
+	border: #999999 solid thin;
223
+}
224
+
225
+#copyright {
226
+	margin-top:15px;
227
+} 
228
+
229
+/*#toc_table {
230
+	text-padding : 5px 5px 5px 5px;
231
+}*/
232
+
233
+h1.categorytitle {
234
+	text-align:center;
235
+	text-decoration:none;
236
+	border-bottom:none;
237
+}
238
+
239
+tr.d_del{background:red;}
240
+tr.d_add{background:green;}

+ 62
- 0
misk/discount.patch View File

@@ -0,0 +1,62 @@
1
+Common subdirectories: discount-2.0.3/Plan9 and discount-2.0.3-side/Plan9
2
+Common subdirectories: discount-2.0.3/tests and discount-2.0.3-side/tests
3
+diff -u discount-2.0.3/toc.c discount-2.0.3-side/toc.c
4
+--- discount-2.0.3/toc.c	2010-11-27 08:44:44.000000000 +0200
5
++++ discount-2.0.3-side/toc.c	2010-12-31 18:25:17.000000000 +0200
6
+@@ -21,6 +21,7 @@
7
+ {
8
+     Paragraph *tp, *srcp;
9
+     int last_hnumber = 0;
10
++    int last_limit = 6;
11
+     Cstring res;
12
+     
13
+     *doc = 0;
14
+@@ -31,6 +32,26 @@
15
+     CREATE(res);
16
+     RESERVE(res, 100);
17
+ 
18
++    /*
19
++     * Find the minimal heading level, useful in cases
20
++     * when h1 is already in use (like article title and
21
++     * in markdown only h2, h3 or even higher are used
22
++     *
23
++     * So list nesting would be done from min_header
24
++     */
25
++    for ( tp = p->code; tp ; tp = tp->next ) {
26
++	if ( tp->typ == SOURCE ) {
27
++	    for ( srcp = tp->down; srcp; srcp = srcp->next ) {
28
++		if ( srcp->typ == HDR && srcp->text ) {
29
++			if(srcp->hnumber < last_limit + 1)
30
++				last_limit = srcp->hnumber - 1;
31
++		}
32
++	    }
33
++	}
34
++    }
35
++
36
++    last_hnumber = last_limit;
37
++
38
+     for ( tp = p->code; tp ; tp = tp->next ) {
39
+ 	if ( tp->typ == SOURCE ) {
40
+ 	    for ( srcp = tp->down; srcp; srcp = srcp->next ) {
41
+@@ -45,7 +66,7 @@
42
+ 
43
+ 		    while ( srcp->hnumber > last_hnumber ) {
44
+ 			Csprintf(&res, "%*s%s<ul>\n", last_hnumber, "",
45
+-				    last_hnumber ? "<li>" : "");
46
++				    ( last_hnumber != last_limit )? "<li>" : "");
47
+ 			++last_hnumber;
48
+ 		    }
49
+ 		    Csprintf(&res, "%*s<li><a href=\"#", srcp->hnumber, "");
50
+@@ -61,9 +82,9 @@
51
+         }
52
+     }
53
+ 
54
+-    while ( last_hnumber > 0 ) {
55
++    while ( last_hnumber > last_limit ) {
56
+ 	--last_hnumber;
57
+-	Csprintf(&res, last_hnumber ? "%*s</ul></li>\n" : "%*s</ul>\n", last_hnumber, "");
58
++	Csprintf(&res, (last_hnumber != last_limit ) ? "%*s</ul></li>\n" : "%*s</ul>\n", last_hnumber, "");
59
+     }
60
+ 			/* HACK ALERT! HACK ALERT! HACK ALERT! */
61
+     *doc = T(res);	/* we know that a T(Cstring) is a character pointer */
62
+Common subdirectories: discount-2.0.3/tools and discount-2.0.3-side/tools

+ 305
- 0
po/he.po View File

@@ -0,0 +1,305 @@
1
+# translation of he.po to Hebrew
2
+# translation of he.po to
3
+# translation of wikipp.po to
4
+# Hebrew Translation.
5
+# Copyright (C) YEAR Artyom Tonkikh
6
+# This file is distributed under the same license as the wikipp package.
7
+#
8
+# Artyom Tonkikg <artyomtnk@yahoo.com>, 2008.
9
+# artik <artyomtnk@yahoo.com>, 2008, 2009, 2010, 2012.
10
+msgid ""
11
+msgstr ""
12
+"Project-Id-Version: he\n"
13
+"Report-Msgid-Bugs-To: \n"
14
+"POT-Creation-Date: 2012-02-01 13:06+0200\n"
15
+"PO-Revision-Date: 2012-02-01 13:08+0200\n"
16
+"Last-Translator: Artyom <artyomtnk@yahoo.com>\n"
17
+"Language-Team: Hebrew <>\n"
18
+"Language: he\n"
19
+"MIME-Version: 1.0\n"
20
+"Content-Type: text/plain; charset=UTF-8\n"
21
+"Content-Transfer-Encoding: 8bit\n"
22
+"X-Generator: Lokalize 1.2\n"
23
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
24
+
25
+#: master.cpp:110
26
+msgid "LANG"
27
+msgstr "עברית"
28
+
29
+#: options.cpp:14
30
+msgid "Users Only"
31
+msgstr "משתמשים בלבד"
32
+
33
+#: options.cpp:15
34
+msgid "Contact e-mail"
35
+msgstr "דוא\"ל ליצירת־קשר"
36
+
37
+#: options.cpp:16
38
+msgid "Wiki Title"
39
+msgstr "כותרת הויקי"
40
+
41
+#: options.cpp:17
42
+msgid "About Wiki"
43
+msgstr "אודות ויקי"
44
+
45
+#: options.cpp:18
46
+msgid "Copyright String"
47
+msgstr "זכויות היוצרים"
48
+
49
+#: options.cpp:19 users.cpp:45
50
+msgid "Submit"
51
+msgstr "שלח"
52
+
53
+#: options.cpp:32
54
+msgid "Disable creation of new articles by visitors"
55
+msgstr "בטל יצירת מאמרים חדשים ע\" מבקרים"
56
+
57
+#: options.cpp:110
58
+msgid "Wiki++ - CppCMS Wiki"
59
+msgstr "ויקי++ - ויקי על CppCMS"
60
+
61
+#: options.cpp:113
62
+msgid ""
63
+"## About\n"
64
+"\n"
65
+"Wiki++ is a wiki engine powered by\n"
66
+"[CppCMS](http://cppcms.sf.net/) web development framework.\n"
67
+msgstr ""
68
+"## אודות\n"
69
+"\n"
70
+"ויקי++ זה מנוע ויקי מבוסס על תשתית פיתוח אינטרנט [CppCMS](http://cppcms.sf."
71
+"net/)\n"
72
+
73
+#: options.cpp:118
74
+msgid "(C) All Rights Reserved"
75
+msgstr "‏(C) ‏ כל הזכויות שמורות"
76
+
77
+#: page.cpp:17
78
+msgid "Title"
79
+msgstr "כותרת"
80
+
81
+#: page.cpp:18 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:111
82
+msgid "Content"
83
+msgstr "תוכן"
84
+
85
+#: page.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:115
86
+msgid "Sidebar"
87
+msgstr "סרגל־צד"
88
+
89
+#: page.cpp:20
90
+msgid "Save"
91
+msgstr "שמור"
92
+
93
+#: page.cpp:21
94
+msgid "Save and Continue"
95
+msgstr "שמור והמשך"
96
+
97
+#: page.cpp:22
98
+msgid "Preview"
99
+msgstr "תצוגה מקדימה"
100
+
101
+#: page.cpp:32
102
+msgid "Disable editing by visitors"
103
+msgstr "בטל עריכה למבקרים"
104
+
105
+#: page.cpp:33
106
+msgid "Please Login"
107
+msgstr "אנא התחבר"
108
+
109
+#: users.cpp:17 users.cpp:41
110
+msgid "Username"
111
+msgstr "שם משתמש"
112
+
113
+#: users.cpp:18 users.cpp:42
114
+msgid "Password"
115
+msgstr "ססמה"
116
+
117
+#: users.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:65
118
+msgid "Login"
119
+msgstr "התחברות"
120
+
121
+#: users.cpp:43
122
+msgid "Confirm"
123
+msgstr "אמת"
124
+
125
+#: users.cpp:44
126
+msgid "Solve"
127
+msgstr "פתור"
128
+
129
+#: users.cpp:79
130
+msgid "This user exists"
131
+msgstr "המשתמש קיים"
132
+
133
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:5
134
+msgid "Wellcome to WikiPP"
135
+msgstr "ברוכים הבאים ל־ויקי++"
136
+
137
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:9
138
+msgid " Users Area"
139
+msgstr "אזור משתמשים"
140
+
141
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:14
142
+msgid "Navigation"
143
+msgstr "ניווט"
144
+
145
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:16
146
+msgid "Index"
147
+msgstr "אינדקס"
148
+
149
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:17
150
+msgid "Changes"
151
+msgstr "שינויים"
152
+
153
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:20
154
+msgid "Main Page"
155
+msgstr "עמוד ראשי"
156
+
157
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:42
158
+msgid "LTR"
159
+msgstr "RTL"
160
+
161
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:68
162
+msgid "Logout "
163
+msgstr "יציאה"
164
+
165
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:78
166
+msgid "Main"
167
+msgstr "ראשי"
168
+
169
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:90
170
+msgid "Valid CSS"
171
+msgstr "‏css תקני"
172
+
173
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:91
174
+msgid "Valid XHTML 1.0"
175
+msgstr "‏XHTML 1.0 תקני"
176
+
177
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:96
178
+msgid ""
179
+"Template design based on <a href=\"http://ContentedDesigns.com\">Contented "
180
+"Designs</a>"
181
+msgstr ""
182
+"התבנית מבוססת על עיצוב <a href=\"http://ContentedDesigns.com\">Contented "
183
+"Designs</a>"
184
+
185
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:99
186
+msgid "Contact"
187
+msgstr "צור קשר"
188
+
189
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:14
190
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
191
+msgid "Edit"
192
+msgstr "עריכה"
193
+
194
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:16
195
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:31
196
+msgid "History"
197
+msgstr "היסטוריה"
198
+
199
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
200
+msgid "New Article"
201
+msgstr "מאמר חדש"
202
+
203
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:29
204
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:5
205
+msgid "Back to page"
206
+msgstr "חזרה מאמר"
207
+
208
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:68
209
+msgid "Edit this version (rollback)"
210
+msgstr "ערוך גרסה זו (שחזור)"
211
+
212
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:73
213
+msgid "(version {1,num}, from {2,dt=s})"
214
+msgstr "(גרסה {1}, ב־{2,dt=s})"
215
+
216
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:78
217
+msgid "Difference \"{1}\" ver. {2} versus ver. {3}"
218
+msgstr "השוואה של \"{1}\", גרסה {2}, גרסה {3}"
219
+
220
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:80
221
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:82
222
+msgid "Edit version {1,num}"
223
+msgstr "ערוך גרסה {1,num}"
224
+
225
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:99
226
+msgid "No such page or version exist"
227
+msgstr "עמוד או גרסאות כאלה לא קיימים"
228
+
229
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:101
230
+msgid "No difference between these versions"
231
+msgstr "אין הבדל בין הגרסאות"
232
+
233
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:104
234
+msgid "Titles"
235
+msgstr "כותרות"
236
+
237
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:106
238
+msgid "Version {1}"
239
+msgstr "גרסה {1}"
240
+
241
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:3
242
+msgid "WikiPP :: History"
243
+msgstr "ויקי++ :: היסטוריה"
244
+
245
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:14
246
+msgid "Version {1,num}, changed at {2,dt=s}, by {3}"
247
+msgstr "גרסה {,num1}, עודכנה ב־{2,dt=s} ע\"י {3}"
248
+
249
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:15
250
+msgid "Show"
251
+msgstr "הצג"
252
+
253
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:16
254
+msgid "Edit (rollback)"
255
+msgstr "עריכה (שחזור)"
256
+
257
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:17
258
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:33
259
+msgid "Diff to previous"
260
+msgstr "השוואה עם גרסה קודמת"
261
+
262
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:23
263
+msgid "History is empty"
264
+msgstr "היסטוריה ריקה"
265
+
266
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:25
267
+msgid "Next page"
268
+msgstr "עמוד הבא"
269
+
270
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:3
271
+msgid "WikiPP :: Login"
272
+msgstr "ויקי++ :: כניסה"
273
+
274
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:11
275
+msgid "Register as new user"
276
+msgstr "הרשם כמשתמש חדש"
277
+
278
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:16
279
+msgid "WikiPP :: Register"
280
+msgstr "ויקי :: הרשמה"
281
+
282
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:38
283
+msgid "WikiPP :: Edit Options"
284
+msgstr "ויקי :: עריכת הגדרות"
285
+
286
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:4
287
+msgid "Index of Articles"
288
+msgstr "אינדקס מאמרים"
289
+
290
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:26
291
+msgid "Recent Changes"
292
+msgstr "שינויים אחרונים"
293
+
294
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:32
295
+msgid "version {1,num}, at {2,dt=s}, by {3}"
296
+msgstr "גרסה {1}, ב־{2,dt=s}, ע\"י {3}"
297
+
298
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:38
299
+msgid "Next Page"
300
+msgstr "עמוד הבא"
301
+
302
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:40
303
+msgid "No more changes"
304
+msgstr "אין יותר שינויים"
305
+

+ 303
- 0
po/pl.po View File

@@ -0,0 +1,303 @@
1
+# translation of pl.po to Hebrew
2
+# Translation of Wiki++ to Polish.
3
+# Copyright (C) 2010 Michał Fita
4
+# This file is distributed under the same license as the Wiki++ package.
5
+#
6
+# Michal Fita <michal.fita@gmail.com>, 2010.
7
+# artik <artyomtnk@yahoo.com>, 2010, 2012.
8
+msgid ""
9
+msgstr ""
10
+"Project-Id-Version: pl\n"
11
+"Report-Msgid-Bugs-To: \n"
12
+"POT-Creation-Date: 2012-02-01 13:06+0200\n"
13
+"PO-Revision-Date: 2012-02-01 13:10+0200\n"
14
+"Last-Translator: Artyom <artyomtnk@yahoo.com>\n"
15
+"Language-Team: Hebrew <>\n"
16
+"Language: he\n"
17
+"MIME-Version: 1.0\n"
18
+"Content-Type: text/plain; charset=UTF-8\n"
19
+"Content-Transfer-Encoding: 8bit\n"
20
+"X-Generator: Lokalize 1.2\n"
21
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
22
+
23
+#: master.cpp:110
24
+msgid "LANG"
25
+msgstr "Polski"
26
+
27
+#: options.cpp:14
28
+msgid "Users Only"
29
+msgstr ""
30
+
31
+#: options.cpp:15
32
+msgid "Contact e-mail"
33
+msgstr "Adres kontaktowy"
34
+
35
+#: options.cpp:16
36
+msgid "Wiki Title"
37
+msgstr "Tytuł wiki"
38
+
39
+#: options.cpp:17
40
+msgid "About Wiki"
41
+msgstr "O wiki"
42
+
43
+#: options.cpp:18
44
+msgid "Copyright String"
45
+msgstr ""
46
+
47
+#: options.cpp:19 users.cpp:45
48
+msgid "Submit"
49
+msgstr "Wyślij"
50
+
51
+#: options.cpp:32
52
+msgid "Disable creation of new articles by visitors"
53
+msgstr "Wyłącza tworzenie nowych artykułów przez gości"
54
+
55
+#: options.cpp:110
56
+msgid "Wiki++ - CppCMS Wiki"
57
+msgstr ""
58
+
59
+#: options.cpp:113
60
+msgid ""
61
+"## About\n"
62
+"\n"
63
+"Wiki++ is a wiki engine powered by\n"
64
+"[CppCMS](http://cppcms.sf.net/) web development framework.\n"
65
+msgstr ""
66
+"## O\n"
67
+"\n"
68
+"Wiki++ jest silnikiem wiki napędzanym\n"
69
+"szkieletem [CppCMS](http://cppcms.sf.net/) dla aplikacji web.\n"
70
+
71
+#: options.cpp:118
72
+msgid "(C) All Rights Reserved"
73
+msgstr "(C) Wszelkie prawa zastrzeżone"
74
+
75
+#: page.cpp:17
76
+msgid "Title"
77
+msgstr "Tytuł"
78
+
79
+#: page.cpp:18 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:111
80
+msgid "Content"
81
+msgstr "Zawartość"
82
+
83
+#: page.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:115
84
+msgid "Sidebar"
85
+msgstr ""
86
+
87
+#: page.cpp:20
88
+msgid "Save"
89
+msgstr "Zapisz"
90
+
91
+#: page.cpp:21
92
+msgid "Save and Continue"
93
+msgstr "Zapisz i kontynuuj"
94
+
95
+#: page.cpp:22
96
+msgid "Preview"
97
+msgstr "Podgląd"
98
+
99
+#: page.cpp:32
100
+msgid "Disable editing by visitors"
101
+msgstr "Wyłącz edycję przez gości"
102
+
103
+#: page.cpp:33
104
+msgid "Please Login"
105
+msgstr "Proszę się zalogować"
106
+
107
+#: users.cpp:17 users.cpp:41
108
+msgid "Username"
109
+msgstr "Nazwa użytkownika"
110
+
111
+#: users.cpp:18 users.cpp:42
112
+msgid "Password"
113
+msgstr "Hasło"
114
+
115
+#: users.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:65
116
+msgid "Login"
117
+msgstr "Logowanie"
118
+
119
+#: users.cpp:43
120
+msgid "Confirm"
121
+msgstr "Potwierdź"
122
+
123
+#: users.cpp:44
124
+msgid "Solve"
125
+msgstr ""
126
+
127
+#: users.cpp:79
128
+msgid "This user exists"
129
+msgstr "Taki użytkownik istnieje"
130
+
131
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:5
132
+msgid "Wellcome to WikiPP"
133
+msgstr "Zapraszamy do WikiPP"
134
+
135
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:9
136
+msgid " Users Area"
137
+msgstr " Obszar użytkownika"
138
+
139
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:14
140
+msgid "Navigation"
141
+msgstr "Nawigacja"
142
+
143
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:16
144
+msgid "Index"
145
+msgstr "Indeks"
146
+
147
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:17
148
+msgid "Changes"
149
+msgstr "Zmiany"
150
+
151
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:20
152
+msgid "Main Page"
153
+msgstr "Strona główna"
154
+
155
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:42
156
+msgid "LTR"
157
+msgstr "LTR"
158
+
159
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:68
160
+msgid "Logout "
161
+msgstr "Wyloguj "
162
+
163
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:78
164
+msgid "Main"
165
+msgstr "Główna"
166
+
167
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:90
168
+msgid "Valid CSS"
169
+msgstr "Poprawny CSS"
170
+
171
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:91
172
+msgid "Valid XHTML 1.0"
173
+msgstr "Poprawny XTML 1.0"
174
+
175
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:96
176
+msgid ""
177
+"Template design based on <a href=\"http://ContentedDesigns.com\">Contented "
178
+"Designs</a>"
179
+msgstr ""
180
+"Projekt wzorca bazuja na <a href=\"http://ContentedDesigns.com\">Contented "
181
+"Designs</a>"
182
+
183
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:99
184
+msgid "Contact"
185
+msgstr "Kontakt"
186
+
187
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:14
188
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
189
+msgid "Edit"
190
+msgstr "Edycja"
191
+
192
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:16
193
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:31
194
+msgid "History"
195
+msgstr "Histora"
196
+
197
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
198
+msgid "New Article"
199
+msgstr "Nowy artykuł"
200
+
201
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:29
202
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:5
203
+msgid "Back to page"
204
+msgstr "Powrót do strony"
205
+
206
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:68
207
+msgid "Edit this version (rollback)"
208
+msgstr "Edycja tej wersji (przywrócenie)"
209
+
210
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:73
211
+msgid "(version {1,num}, from {2,dt=s})"
212
+msgstr "(wersja {1,ord}, z {2,dt=s})"
213
+
214
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:78
215
+msgid "Difference \"{1}\" ver. {2} versus ver. {3}"
216
+msgstr "Różnica \"{1}\" w. {2} w stosunku do w. {3}"
217
+
218
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:80
219
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:82
220
+msgid "Edit version {1,num}"
221
+msgstr "Edycja wersji {1,num}"
222
+
223
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:99
224
+msgid "No such page or version exist"
225
+msgstr "Wybrana strona lub wersja nie istnieje"
226
+
227
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:101
228
+msgid "No difference between these versions"
229
+msgstr "Brak różnic między tymi wersjami"
230
+
231
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:104
232
+msgid "Titles"
233
+msgstr "Tytuły"
234
+
235
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:106
236
+msgid "Version {1}"
237
+msgstr "Wersja {1}"
238
+
239
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:3
240
+msgid "WikiPP :: History"
241
+msgstr "WikiPP :: Historia"
242
+
243
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:14
244
+msgid "Version {1,num}, changed at {2,dt=s}, by {3}"
245
+msgstr "Wersja {1,num}, zmieniona {2,dt=s}, przez {3}"
246
+
247
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:15
248
+msgid "Show"
249
+msgstr "Pokaż"
250
+
251
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:16
252
+msgid "Edit (rollback)"
253
+msgstr "Edytuj (przywróć)"
254
+
255
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:17
256
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:33
257
+msgid "Diff to previous"
258
+msgstr "Różnice z poprzednią"
259
+
260
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:23
261
+msgid "History is empty"
262
+msgstr "Historia jest pusta"
263
+
264
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:25
265
+msgid "Next page"
266
+msgstr "Następna strona"
267
+
268
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:3
269
+msgid "WikiPP :: Login"
270
+msgstr "WikiPP :: Logowanie"
271
+
272
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:11
273
+msgid "Register as new user"
274
+msgstr "Rejestracja jako nowy użytkownik"
275
+
276
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:16
277
+msgid "WikiPP :: Register"
278
+msgstr "WikiPP :: Rejestracja"
279
+
280
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:38
281
+msgid "WikiPP :: Edit Options"
282
+msgstr "WikiPP :: Edycja opcji"
283
+
284
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:4
285
+msgid "Index of Articles"
286
+msgstr "Index artykułów"
287
+
288
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:26
289
+msgid "Recent Changes"
290
+msgstr "Ostatnie zmiany"
291
+
292
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:32
293
+msgid "version {1,num}, at {2,dt=s}, by {3}"
294
+msgstr "wersja {1,num}, z {2,dt=s}, przez {3}"
295
+
296
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:38
297
+msgid "Next Page"
298
+msgstr "Następna strona"
299
+
300
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:40
301
+msgid "No more changes"
302
+msgstr "Nie ma więcej zmian"
303
+

+ 307
- 0
po/ru.po View File

@@ -0,0 +1,307 @@
1
+# translation of ru.po to Hebrew
2
+# translation of he.po to
3
+# translation of wikipp.po to
4
+# Hebrew Translation.
5
+# Copyright (C) YEAR Artyom Tonkikh
6
+# This file is distributed under the same license as the wikipp package.
7
+#
8
+# Artyom Tonkikg <artyomtnk@yahoo.com>, 2008.
9
+# artik <artyomtnk@yahoo.com>, 2008, 2009, 2010, 2012.
10
+msgid ""
11
+msgstr ""
12
+"Project-Id-Version: ru\n"
13
+"Report-Msgid-Bugs-To: \n"
14
+"POT-Creation-Date: 2012-02-01 13:06+0200\n"
15
+"PO-Revision-Date: 2012-02-01 13:09+0200\n"
16
+"Last-Translator: Artyom <artyomtnk@yahoo.com>\n"
17
+"Language-Team: Hebrew <>\n"
18
+"Language: he\n"
19
+"MIME-Version: 1.0\n"
20
+"Content-Type: text/plain; charset=UTF-8\n"
21
+"Content-Transfer-Encoding: 8bit\n"
22
+"X-Generator: Lokalize 1.2\n"
23
+"X-Poedit-Language: Russian\n"
24
+"X-Poedit-Country: RUSSIAN FEDERATION\n"
25
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
26
+
27
+#: master.cpp:110
28
+msgid "LANG"
29
+msgstr "Русский"
30
+
31
+#: options.cpp:14
32
+msgid "Users Only"
33
+msgstr "Только для пользователей"
34
+
35
+#: options.cpp:15
36
+msgid "Contact e-mail"
37
+msgstr "Контактный e-mail"
38
+
39
+#: options.cpp:16
40
+msgid "Wiki Title"
41
+msgstr "Wiki Заголовок"
42
+
43
+#: options.cpp:17
44
+msgid "About Wiki"
45
+msgstr "О Wiki"
46
+
47
+#: options.cpp:18
48
+msgid "Copyright String"
49
+msgstr "Строка копирайта"
50
+
51
+#: options.cpp:19 users.cpp:45
52
+msgid "Submit"
53
+msgstr "Отправить"
54
+
55
+#: options.cpp:32
56
+msgid "Disable creation of new articles by visitors"
57
+msgstr "Отключить создание новых статей посетителями"
58
+
59
+#: options.cpp:110
60
+msgid "Wiki++ - CppCMS Wiki"
61
+msgstr "Wiki++ - CppCMS Вики"
62
+
63
+#: options.cpp:113
64
+msgid ""
65
+"## About\n"
66
+"\n"
67
+"Wiki++ is a wiki engine powered by\n"
68
+"[CppCMS](http://cppcms.sf.net/) web development framework.\n"
69
+msgstr ""
70
+"## Обшие сведения\n"
71
+"\n"
72
+"Wiki++ - это wiki-движок, основанный на\n"
73
+"[CppCMS](http://cppcms.sf.net/) фрэймворке веб-разработки.\n"
74
+
75
+#: options.cpp:118
76
+msgid "(C) All Rights Reserved"
77
+msgstr "(C) Все права защищены"
78
+
79
+#: page.cpp:17
80
+msgid "Title"
81
+msgstr "Заголовок"
82
+
83
+#: page.cpp:18 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:111
84
+msgid "Content"
85
+msgstr "Содержимое"
86
+
87
+#: page.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:115
88
+msgid "Sidebar"
89
+msgstr "Панель"
90
+
91
+#: page.cpp:20
92
+msgid "Save"
93
+msgstr "Сохранить"
94
+
95
+#: page.cpp:21
96
+msgid "Save and Continue"
97
+msgstr "Сохранить и продолжить"
98
+
99
+#: page.cpp:22
100
+msgid "Preview"
101
+msgstr "Просмотр"
102
+
103
+#: page.cpp:32
104
+msgid "Disable editing by visitors"
105
+msgstr "Отключить правку посетителями"
106
+
107
+#: page.cpp:33
108
+msgid "Please Login"
109
+msgstr "Войдите пожалуйста"
110
+
111
+#: users.cpp:17 users.cpp:41
112
+msgid "Username"
113
+msgstr "Имя пользователя"
114
+
115
+#: users.cpp:18 users.cpp:42
116
+msgid "Password"
117
+msgstr "Пароль"
118
+
119
+#: users.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:65
120
+msgid "Login"
121
+msgstr "Логин"
122
+
123
+#: users.cpp:43
124
+msgid "Confirm"
125
+msgstr "Подтвердить"
126
+
127
+#: users.cpp:44
128
+msgid "Solve"
129
+msgstr "Решить"
130
+
131
+#: users.cpp:79
132
+msgid "This user exists"
133
+msgstr "Такой пользователь существует"
134
+
135
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:5
136
+msgid "Wellcome to WikiPP"
137
+msgstr "Добро пожаловать в WikiPP"
138
+
139
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:9
140
+msgid " Users Area"
141
+msgstr "Область пользователей"
142
+
143
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:14
144
+msgid "Navigation"
145
+msgstr "Навигация"
146
+
147
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:16
148
+msgid "Index"
149
+msgstr "Список"
150
+
151
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:17
152
+msgid "Changes"
153
+msgstr "Изменения"
154
+
155
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:20
156
+msgid "Main Page"
157
+msgstr "Главная страница"
158
+
159
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:42
160
+msgid "LTR"
161
+msgstr "LTR"
162
+
163
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:68
164
+msgid "Logout "
165
+msgstr "Выйти "
166
+
167
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:78
168
+msgid "Main"
169
+msgstr "Главная"
170
+
171
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:90
172
+msgid "Valid CSS"
173
+msgstr "Валидация CSS"
174
+
175
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:91
176
+msgid "Valid XHTML 1.0"
177
+msgstr "Валидация XHTML 1.0"
178
+
179
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:96
180
+msgid ""
181
+"Template design based on <a href=\"http://ContentedDesigns.com\">Contented "
182
+"Designs</a>"
183
+msgstr ""
184
+"Дизайн шаблонов основан на <a href=\"http://ContentedDesigns.com\"> "
185
+"Contented Designs</a>"
186
+
187
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:99
188
+msgid "Contact"
189
+msgstr "Контакты"
190
+
191
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:14
192
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
193
+msgid "Edit"
194
+msgstr "Правка"
195
+
196
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:16
197
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:31
198
+msgid "History"
199
+msgstr "История"
200
+
201
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
202
+msgid "New Article"
203
+msgstr "Новая статья"
204
+
205
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:29
206
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:5
207
+msgid "Back to page"
208
+msgstr "Вернуться к странице"
209
+
210
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:68
211
+msgid "Edit this version (rollback)"
212
+msgstr "Редактировать это версию (откат)"
213
+
214
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:73
215
+msgid "(version {1,num}, from {2,dt=s})"
216
+msgstr "(версия {1,num}, от {2,dt=s})"
217
+
218
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:78
219
+msgid "Difference \"{1}\" ver. {2} versus ver. {3}"
220
+msgstr "Отличия \"{1}\" вер. {2} сравн. вер. {3}"
221
+
222
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:80
223
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:82
224
+msgid "Edit version {1,num}"
225
+msgstr "Правка версии {1,num}"
226
+
227
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:99
228
+msgid "No such page or version exist"
229
+msgstr "Такой страницы или версии не существует"
230
+
231
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:101
232
+msgid "No difference between these versions"
233
+msgstr "Нет различий между этими версиями"
234
+
235
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:104
236
+msgid "Titles"
237
+msgstr "Заголовки"
238
+
239
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:106
240
+msgid "Version {1}"
241
+msgstr "Версия {1}"
242
+
243
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:3
244
+msgid "WikiPP :: History"
245
+msgstr "WikiPP :: История"
246
+
247
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:14
248
+msgid "Version {1,num}, changed at {2,dt=s}, by {3}"
249
+msgstr "Версия {1,num}, изменена {2,dt=s}, {3}"
250
+
251
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:15
252
+msgid "Show"
253
+msgstr "Показать"
254
+
255
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:16
256
+msgid "Edit (rollback)"
257
+msgstr "Правка (откат)"
258
+
259
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:17
260
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:33
261
+msgid "Diff to previous"
262
+msgstr "Различия с прежним"
263
+
264
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:23
265
+msgid "History is empty"
266
+msgstr "История пуста"
267
+
268
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:25
269
+msgid "Next page"
270
+msgstr "Следующая страница"
271
+
272
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:3
273
+msgid "WikiPP :: Login"
274
+msgstr "WikiPP :: Вход"
275
+
276
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:11
277
+msgid "Register as new user"
278
+msgstr "Зарегистрируйтесь как новый пользователь"
279
+
280
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:16
281
+msgid "WikiPP :: Register"
282
+msgstr "WikiPP :: Регистрация"
283
+
284
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:38
285
+msgid "WikiPP :: Edit Options"
286
+msgstr "WikiPP :: Редактировать опции"
287
+
288
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:4
289
+msgid "Index of Articles"
290
+msgstr "Список статей"
291
+
292
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:26
293
+msgid "Recent Changes"
294
+msgstr "Последние Изменения"
295
+
296
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:32
297
+msgid "version {1,num}, at {2,dt=s}, by {3}"
298
+msgstr "версия {1,num}, от {2,dt=s}, {3}"
299
+
300
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:38
301
+msgid "Next Page"
302
+msgstr "Следующая страница"
303
+
304
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:40
305
+msgid "No more changes"
306
+msgstr "Больше нет изменений"
307
+

+ 293
- 0
po/wikipp.pot View File

@@ -0,0 +1,293 @@
1
+# SOME DESCRIPTIVE TITLE.
2
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+# This file is distributed under the same license as the PACKAGE package.
4
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+#
6
+#, fuzzy
7
+msgid ""
8
+msgstr ""
9
+"Project-Id-Version: PACKAGE VERSION\n"
10
+"Report-Msgid-Bugs-To: \n"
11
+"POT-Creation-Date: 2012-02-01 13:06+0200\n"
12
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
+"Language-Team: LANGUAGE <LL@li.org>\n"
15
+"Language: \n"
16
+"MIME-Version: 1.0\n"
17
+"Content-Type: text/plain; charset=CHARSET\n"
18
+"Content-Transfer-Encoding: 8bit\n"
19
+
20
+#: master.cpp:110
21
+msgid "LANG"
22
+msgstr ""
23
+
24
+#: options.cpp:14
25
+msgid "Users Only"
26
+msgstr ""
27
+
28
+#: options.cpp:15
29
+msgid "Contact e-mail"
30
+msgstr ""
31
+
32
+#: options.cpp:16
33
+msgid "Wiki Title"
34
+msgstr ""
35
+
36
+#: options.cpp:17
37
+msgid "About Wiki"
38
+msgstr ""
39
+
40
+#: options.cpp:18
41
+msgid "Copyright String"
42
+msgstr ""
43
+
44
+#: options.cpp:19 users.cpp:45
45
+msgid "Submit"
46
+msgstr ""
47
+
48
+#: options.cpp:32
49
+msgid "Disable creation of new articles by visitors"
50
+msgstr ""
51
+
52
+#: options.cpp:110
53
+msgid "Wiki++ - CppCMS Wiki"
54
+msgstr ""
55
+
56
+#: options.cpp:113
57
+msgid ""
58
+"## About\n"
59
+"\n"
60
+"Wiki++ is a wiki engine powered by\n"
61
+"[CppCMS](http://cppcms.sf.net/) web development framework.\n"
62
+msgstr ""
63
+
64
+#: options.cpp:118
65
+msgid "(C) All Rights Reserved"
66
+msgstr ""
67
+
68
+#: page.cpp:17
69
+msgid "Title"
70
+msgstr ""
71
+
72
+#: page.cpp:18 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:111
73
+msgid "Content"
74
+msgstr ""
75
+
76
+#: page.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:115
77
+msgid "Sidebar"
78
+msgstr ""
79
+
80
+#: page.cpp:20
81
+msgid "Save"
82
+msgstr ""
83
+
84
+#: page.cpp:21
85
+msgid "Save and Continue"
86
+msgstr ""
87
+
88
+#: page.cpp:22
89
+msgid "Preview"
90
+msgstr ""
91
+
92
+#: page.cpp:32
93
+msgid "Disable editing by visitors"
94
+msgstr ""
95
+
96
+#: page.cpp:33
97
+msgid "Please Login"
98
+msgstr ""
99
+
100
+#: users.cpp:17 users.cpp:41
101
+msgid "Username"
102
+msgstr ""
103
+
104
+#: users.cpp:18 users.cpp:42
105
+msgid "Password"
106
+msgstr ""
107
+
108
+#: users.cpp:19 /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:65
109
+msgid "Login"
110
+msgstr ""
111
+
112
+#: users.cpp:43
113
+msgid "Confirm"
114
+msgstr ""
115
+
116
+#: users.cpp:44
117
+msgid "Solve"
118
+msgstr ""
119
+
120
+#: users.cpp:79
121
+msgid "This user exists"
122
+msgstr ""
123
+
124
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:5
125
+msgid "Wellcome to WikiPP"
126
+msgstr ""
127
+
128
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:9
129
+msgid " Users Area"
130
+msgstr ""
131
+
132
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:14
133
+msgid "Navigation"
134
+msgstr ""
135
+
136
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:16
137
+msgid "Index"
138
+msgstr ""
139
+
140
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:17
141
+msgid "Changes"
142
+msgstr ""
143
+
144
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:20
145
+msgid "Main Page"
146
+msgstr ""
147
+
148
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:42
149
+msgid "LTR"
150
+msgstr ""
151
+
152
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:68
153
+msgid "Logout "
154
+msgstr ""
155
+
156
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:78
157
+msgid "Main"
158
+msgstr ""
159
+
160
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:90
161
+msgid "Valid CSS"
162
+msgstr ""
163
+
164
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:91
165
+msgid "Valid XHTML 1.0"
166
+msgstr ""
167
+
168
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:96
169
+msgid ""
170
+"Template design based on <a href=\"http://ContentedDesigns.com\">Contented "
171
+"Designs</a>"
172
+msgstr ""
173
+
174
+#: /home/artik/Projects/cppcms/wikipp/templates/main.tmpl:99
175
+msgid "Contact"
176
+msgstr ""
177
+
178
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:14
179
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
180
+msgid "Edit"
181
+msgstr ""
182
+
183
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:16
184
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:31
185
+msgid "History"
186
+msgstr ""
187
+
188
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:26
189
+msgid "New Article"
190
+msgstr ""
191
+
192
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:29
193
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:5
194
+msgid "Back to page"
195
+msgstr ""
196
+
197
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:68
198
+msgid "Edit this version (rollback)"
199
+msgstr ""
200
+
201
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:73
202
+msgid "(version {1,num}, from {2,dt=s})"
203
+msgstr ""
204
+
205
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:78
206
+msgid "Difference \"{1}\" ver. {2} versus ver. {3}"
207
+msgstr ""
208
+
209
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:80
210
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:82
211
+msgid "Edit version {1,num}"
212
+msgstr ""
213
+
214
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:99
215
+msgid "No such page or version exist"
216
+msgstr ""
217
+
218
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:101
219
+msgid "No difference between these versions"
220
+msgstr ""
221
+
222
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:104
223
+msgid "Titles"
224
+msgstr ""
225
+
226
+#: /home/artik/Projects/cppcms/wikipp/templates/page.tmpl:106
227
+msgid "Version {1}"
228
+msgstr ""
229
+
230
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:3
231
+msgid "WikiPP :: History"
232
+msgstr ""
233
+
234
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:14
235
+msgid "Version {1,num}, changed at {2,dt=s}, by {3}"
236
+msgstr ""
237
+
238
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:15
239
+msgid "Show"
240
+msgstr ""
241
+
242
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:16
243
+msgid "Edit (rollback)"
244
+msgstr ""
245
+
246
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:17
247
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:33
248
+msgid "Diff to previous"
249
+msgstr ""
250
+
251
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:23
252
+msgid "History is empty"
253
+msgstr ""
254
+
255
+#: /home/artik/Projects/cppcms/wikipp/templates/hist.tmpl:25
256
+msgid "Next page"
257
+msgstr ""
258
+
259
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:3
260
+msgid "WikiPP :: Login"
261
+msgstr ""
262
+
263
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:11
264
+msgid "Register as new user"
265
+msgstr ""
266
+
267
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:16
268
+msgid "WikiPP :: Register"
269
+msgstr ""
270
+
271
+#: /home/artik/Projects/cppcms/wikipp/templates/admin.tmpl:38
272
+msgid "WikiPP :: Edit Options"
273
+msgstr ""
274
+
275
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:4
276
+msgid "Index of Articles"
277
+msgstr ""
278
+
279
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:26
280
+msgid "Recent Changes"
281
+msgstr ""
282
+
283
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:32
284
+msgid "version {1,num}, at {2,dt=s}, by {3}"
285
+msgstr ""
286
+
287
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:38
288
+msgid "Next Page"
289
+msgstr ""
290
+
291
+#: /home/artik/Projects/cppcms/wikipp/templates/toc.tmpl:40
292
+msgid "No more changes"
293
+msgstr ""

+ 103
- 0
sample_config.js View File

@@ -0,0 +1,103 @@
1
+{
2
+	"wikipp" : {
3
+
4
+		"script" : "/wikipp",
5
+		"media" :"/media/",
6
+		
7
+		//
8
+		// Set a path to hightligher to enable it
9
+		//
10
+		// "syntax_highlighter" : "/media/sh",
11
+		//
12
+
13
+		"disable_registration" : false,
14
+
15
+		"languages" : {
16
+			"en" : "en_US.UTF-8" ,
17
+			"he" : "he_IL.UTF-8" ,
18
+			"ru" : "ru_RU.UTF-8" ,
19
+			"pl" : "pl_PL.UTF-8"
20
+		},
21
+
22
+		//
23
+		// Setup connection string for DB
24
+		//
25
+
26
+		// Sqlite3 Sample Connection String
27
+		//"connection_string" : "sqlite3:db=/var/wikipp/db/wikipp.db;@pool_size=16",
28
+		//
29
+		// PostgreSQL Sample Connection String
30
+		// "connection_string" : "postgresql:dbname=wikipp;@pool_size=16",
31
+		//
32
+		// MySQL Sample Connection String
33
+		//
34
+		// "connection_string" : "mysql:database=wikipp;user=root;password=root;@pool_size=16",
35
+		//
36
+		// In Some cases mysql works faster without prepared statements as it uses query cache, so you
37
+		// may change this string to:
38
+		//
39
+		// "connection_string" : "mysql:database=wikipp;user=root;password=root;@pool_size=16;@use_prepared=off",
40
+		//	
41
+	},
42
+	"service" : {
43
+		"api" : "fastcgi",
44
+		"socket" : "stdin"
45
+	},
46
+	"session" : {
47
+		"expire" : "renew",
48
+		"location" : "client",
49
+		"timeout" : 2592000, // One month 24*3600*30
50
+		"cookies" :  {
51
+			"prefix" : "wikipp"
52
+		},
53
+		"client" : {
54
+			"cbc" : "aes",
55
+			"hmac" :        "sha1",
56
+			// setup these values using 
57
+			//
58
+			// cppcms_make_key --hmac sha1 --cbc aes
59
+			//
60
+			// "cbc_key" :     "Generate your own!",
61
+			// "hmac_key" :    "Generate your own"
62
+		}
63
+	},
64
+	"views" : {
65
+		"paths" : [ "/usr/lib/wikipp"] ,
66
+		"skins" : [ "view" ] ,
67
+	},
68
+	"localization" : {
69
+		"messages" : { 
70
+			"paths" : [ "/usr/share/locale"],
71
+			"domains" :  [ "wikipp" ]
72
+		},
73
+		"locales" : [ 
74
+			"he_IL.UTF-8" ,
75
+			"en_US.UTF-8",
76
+			"ru_RU.UTF-8",
77
+			"pl_PL.UTF-8" 
78
+		]
79
+	},
80
+	"logging" : {
81
+		"level" : "info",
82
+		
83
+		//"syslog" : {
84
+		//	"enable": true,
85
+		//	"id" : "WikiPP"
86
+		//},
87
+
88
+		//"file" : {
89
+		//	"name" : "/var/log/wikipp/wikipp.log",
90
+		//	"append" : true
91
+		//}
92
+	},
93
+	"cache" : {
94
+		"backend" : "thread_shared", 
95
+		"limit" : 100, // items - thread cache
96
+	},
97
+	"security" : {
98
+		"csrf" : { "enable" : true }
99
+	}
100
+}
101
+
102
+
103
+

+ 46
- 0
sql/mysql.sql View File

@@ -0,0 +1,46 @@
1
+drop table if exists history;
2
+drop table if exists pages;
3
+drop table if exists connections;
4
+drop table if exists users;
5
+drop table if exists options;
6
+
7
+create table options (
8
+	lang varchar(16) not null,
9
+	name varchar(32) not null,
10
+	value text not null,
11
+	constraint unique(lang,name)
12
+) Engine = InnoDB;
13
+
14
+create table users (
15
+	id integer auto_increment primary key not null,
16
+	username varchar(32) unique not null,
17
+	password varchar(32) not null
18
+) Engine = InnoDB;
19
+
20
+create table pages (
21
+	id integer auto_increment primary key not null,
22
+	lang varchar(16) not null,
23
+	slug varchar(128) not null,
24
+	title varchar(256) not null,
25
+	content text not null,
26
+	sidebar text not null,
27
+	users_only integer not null,
28
+	constraint unique (lang,slug)
29
+) Engine = InnoDB;
30
+
31
+create table history (
32
+	id integer not null,
33
+	version integer not null,
34
+	created datetime not null,
35
+	author varchar(32) not null,
36
+	title varchar(256) not null,
37
+	content text not null,
38
+	sidebar text not null,
39
+	constraint unique(id,version),
40
+	foreign key(id) references pages(id),
41
+	primary key(id,version)
42
+) Engine = InnoDB;
43
+
44
+create index history_timeline on history(created);
45
+
46
+

+ 50
- 0
sql/postgresql.sql View File

@@ -0,0 +1,50 @@
1
+begin;
2
+
3
+drop table if exists history;
4
+drop table if exists pages;
5
+drop table if exists users;
6
+drop table if exists options;
7
+
8
+create table options (
9
+    lang varchar(16) not null,
10
+    name varchar(32) not null,
11
+    value text not null,
12
+    unique(lang,name)
13
+);
14
+
15
+create table users (
16
+    id serial primary key not null,
17
+    username varchar(32) unique not null,
18
+    password varchar(32) not null
19
+) ;
20
+
21
+create table pages (
22
+    id serial primary key not null,
23
+    lang varchar(16) not null,
24
+    slug varchar(128) not null,
25
+    title varchar(256) not null,
26
+    content text not null,
27
+    sidebar text not null,
28
+    users_only integer not null,
29
+    unique (lang,slug)
30
+);
31
+
32
+
33
+create table history (
34
+    id integer not null,
35
+    version integer not null,
36
+    created timestamp not null,
37
+    author varchar(32) not null,
38
+    title varchar(256) not null,
39
+    content text not null,
40
+    sidebar text not null,
41
+    unique(id,version),
42
+    foreign key(id) references pages(id),
43
+    primary key(id,version)
44
+);
45
+
46
+create index history_timeline on history(created);
47
+
48
+commit;
49
+
50
+

+ 46
- 0
sql/sqlite3.sql View File

@@ -0,0 +1,46 @@
1
+begin;
2
+drop table if exists history;
3
+drop table if exists pages;
4
+drop table if exists users;
5
+drop table if exists options;
6
+
7
+create table options (
8
+    lang varchar(16) not null,
9
+    name varchar(32) not null,
10
+    value text not null,
11
+    unique(lang,name)
12
+);
13
+
14
+create table users (
15
+    id integer primary key autoincrement not null,
16
+    username varchar(32) unique not null,
17
+    password varchar(32) not null
18
+) ;
19
+
20
+create table pages (
21
+    id integer primary key autoincrement not null,
22
+    lang varchar(16) not null,
23
+    slug varchar(128) not null,
24
+    title varchar(256) not null,
25
+    content text not null,
26
+    sidebar text not null,
27
+    users_only integer not null,
28
+    unique (lang,slug)
29
+);
30
+
31
+
32
+create table history (
33
+    id integer not null,
34
+    version integer not null,
35
+    created datetime not null,
36
+    author varchar(32) not null,
37
+    title varchar(256) not null,
38
+    content text not null,
39
+    sidebar text not null,
40
+    unique(id,version),
41
+    primary key(id,version)
42
+);
43
+
44
+create index history_timeline on history(created);
45
+
46
+commit;

+ 11
- 0
src/content.h View File

@@ -0,0 +1,11 @@
1
+#ifndef CONTENT_H
2
+#define CONTENT_H
3
+
4
+#include <cstring>
5
+#include "master_content.h"
6
+#include "users_content.h"
7
+#include "page_content.h"
8
+#include "index_content.h" 
9
+#include "options_content.h"
10
+
11
+#endif

+ 73
- 0
src/diff.h View File

@@ -0,0 +1,73 @@
1
+#ifndef DIFF_H
2
+#define DIFF_H
3
+
4
+#include <vector>
5
+#include <string>
6
+
7
+namespace diff {
8
+
9
+typedef std::vector<std::vector<int> > diff_matrix;
10
+
11
+template<typename element>
12
+diff_matrix lcs_length(std::vector<element> const &X,std::vector<element> const &Y)
13
+{
14
+	int m=X.size();
15
+	int n=Y.size();
16
+	diff_matrix C(m+1,std::vector<int>(n+1,0));
17
+	int i,j;
18
+	for(i=1;i<=m;i++) {
19
+		for(j=1;j<=n;j++) {
20
+			if(X[i-1]==Y[j-1]) {
21
+				C[i][j]=C[i-1][j-1]+1;
22
+			}
23
+			else {
24
+				C[i][j]=std::max(C[i][j-1],C[i-1][j]);
25
+			}
26
+		}
27
+	}
28
+	return C;
29
+}
30
+
31
+template<typename element,typename CNT>
32
+void print_diff(diff_matrix const &C,std::vector<element> const &X,std::vector<element> const &Y,int i,int j,CNT &out)
33
+{
34
+	if(i>0 && j>0 && X[i-1]==Y[j-1]){
35
+		print_diff(C,X,Y,i-1,j-1,out);
36
+		out.push_back(make_pair(0,X[i-1]));
37
+	}
38
+	else {
39
+		if(j>0 && (i==0 || C[i][j-1] >= C[i-1][j])){
40
+			print_diff(C,X,Y,i,j-1,out);
41
+			out.push_back(make_pair(1,Y[j-1]));
42
+		}
43
+		else if(i > 0 && (j == 0 || C[i][j-1] < C[i-1][j])) {
44
+			print_diff(C,X,Y,i-1,j,out);
45
+			out.push_back(make_pair(-1,X[i-1]));
46
+		}
47
+	}
48
+}
49
+
50
+template<typename element,typename CNT>
51
+void diff(std::vector<element> const &X,std::vector<element> const &Y,CNT &out)
52
+{
53
+	diff_matrix C=diff::lcs_length(X,Y);
54
+print_diff(C,X,Y,X.size(),Y.size(),out);
55
+}
56
+
57
+} // namespace diff
58
+
59
+std::vector<std::string> split(std::string const &s)
60
+{
61
+	std::vector<std::string> res;
62
+	size_t pos=0,pos2=0;
63
+	while((pos2=s.find('\n',pos))!=std::string::npos) {
64
+		res.push_back(s.substr(pos,pos2-pos));
65
+		pos=pos2+1;
66
+	}
67
+	res.push_back(s.substr(pos));
68
+	return res;
69
+}
70
+
71
+
72
+
73
+#endif

+ 114
- 0
src/index.cpp View File

@@ -0,0 +1,114 @@
1
+#include "index.h"
2
+#include "index_content.h"
3
+#include "wiki.h"
4
+
5
+#include <cppcms/cache_interface.h>
6
+#include <cppcms/url_dispatcher.h>
7
+
8
+namespace apps {
9
+
10
+index::index(wiki &w):
11
+	master(w)
12
+{
13
+	wi.dispatcher().assign("^/index/?",&index::display_index,this);
14
+	wi.dispatcher().assign("^/changes(/?|/(\\d+))$",&index::changes,this,2);
15
+}
16
+
17
+std::string index::index_url()
18
+{
19
+	return wi.root()+"/index/";
20
+}
21
+
22
+std::string index::changes_url(int p)
23
+{
24
+	if(p==0)
25
+		return wi.root()+"/changes/";
26
+	return wi.root()+(booster::locale::format("/changes/{1}") % p).str();
27
+}
28
+
29
+void index::changes(std::string page_no)
30
+{
31
+	std::string key=locale_name+"_changes_"+page_no;
32
+	if(cache().fetch_page(key))
33
+		return;
34
+	int p;
35
+	const unsigned window=30;
36
+	if(page_no.empty())
37
+		p=0;
38
+	else
39
+		p=atoi(page_no.c_str());
40
+	cppdb::result rs;
41
+	cppdb::session sql(conn);
42
+	rs = sql<<
43
+		"SELECT history.title,history.version,history.created,"
44
+		"	history.author,pages.lang,pages.slug "
45
+		"FROM history "
46
+		"JOIN pages ON history.id=pages.id "
47
+		"ORDER BY created DESC "
48
+		"LIMIT ? "
49
+		"OFFSET ?"
50
+		<< window << p*window;
51
+	content::recent_changes c;	
52
+	c.content;
53
+	int n;
54
+	for(n=0;rs.next();n++) {
55
+		c.content.push_back(content::recent_changes::element());
56
+		content::recent_changes::element &d=c.content.back();
57
+		std::string lang,slug;
58
+		std::tm created;
59
+		rs>>d.title>>d.version>>created>>d.author>>lang>>slug;
60
+		d.created = mktime(&created);
61
+		d.url=wi.page.page_version_url(d.version,lang,slug);
62
+		if(d.version>1)
63
+			d.diff_url=wi.page.diff_url(d.version-1,d.version,lang,slug);
64
+	}
65
+	if(c.content.size()==window)
66
+		c.next=changes_url(p+1);
67
+	ini(c);
68
+	render("recent_changes",c);
69
+	cache().store_page(key,60);
70
+	// Cache changes for at most 30 sec
71
+	// Generally -- prevent cache drop with frequent updates
72
+}
73
+
74
+void index::display_index()
75
+{
76
+	std::string key=locale_name+"_toc_index";
77
+	if(cache().fetch_page(key))
78
+		return;
79
+	content::toc c;
80
+	ini(c);
81
+	cppdb::result r;
82
+	cppdb::session sql(conn);
83
+	r=sql<<	"SELECT slug,title FROM pages "
84
+		"WHERE lang=? "
85
+		"ORDER BY title ASC" << locale_name;
86
+	std::string letter="";
87
+	typedef std::multimap<std::string,std::string,std::locale> mapping_type;
88
+	mapping_type mapping(context().locale());
89
+	while(r.next()) {
90
+		std::string slug,t;
91
+		r >> slug >> t;
92
+		mapping.insert(std::pair<std::string,std::string>(t,slug));
93
+	}
94
+	unsigned items=mapping.size();
95
+	unsigned items_left=items/3;
96
+	unsigned items_mid=items*2/3;
97
+
98
+	mapping_type::iterator p=mapping.begin();
99
+	int rows_no = (mapping.size() +2)/3;
100
+	c.table.resize(rows_no,std::vector<content::toc::element>(3));
101
+	for(unsigned i=0;p!=mapping.end();i++,++p) {
102
+
103
+		int col = i / rows_no;
104
+		int row = i % rows_no;
105
+
106
+		content::toc::element &e = c.table.at(row).at(col);
107
+		e.title = p->first;
108
+		e.url=wi.page.page_url(locale_name,p->second);
109
+	}
110
+	render("toc",c);
111
+	cache().store_page(key,30);
112
+	// Cache TOC for at most 30 seconds
113
+}
114
+}

+ 22
- 0
src/index.h View File

@@ -0,0 +1,22 @@
1
+#ifndef INDEX_H
2
+#define INDEX_H
3
+
4
+#include "master.h"
5
+
6
+namespace apps {
7
+
8
+class wiki;
9
+
10
+class index : public master {
11
+	void changes(std::string);
12
+	void display_index();
13
+public:
14
+	index(wiki &);
15
+	std::string index_url();
16
+	std::string changes_url(int n=0);
17
+};
18
+
19
+}
20
+
21
+
22
+#endif

+ 34
- 0
src/index_content.h View File

@@ -0,0 +1,34 @@
1
+#ifndef INDEX_CONTENT_H
2
+#define INDEX_CONTENT_H
3
+
4
+#include "master_content.h"
5
+
6
+namespace content {
7
+
8
+struct toc : public master {
9
+	struct element {
10
+		std::string title;
11
+		std::string url;
12
+	};
13
+	typedef std::vector<std::vector<element> > table_type;
14
+	table_type table;
15
+};
16
+
17
+struct recent_changes : public master {
18
+	struct element {
19
+		std::string title;
20
+		int version;
21
+		time_t created;
22
+		std::string author;
23
+		std::string url;
24
+		std::string diff_url;
25
+	};
26
+	std::vector<element> content;
27
+	std::string next;
28
+};
29
+
30
+
31
+} // namespace content
32
+
33
+
34
+#endif

+ 19
- 0
src/main.cpp View File

@@ -0,0 +1,19 @@
1
+#include <cppcms/service.h>
2
+#include <cppcms/applications_pool.h>
3
+#include <booster/log.h>
4
+#include "wiki.h"
5
+
6
+int main(int argc,char **argv)
7
+{
8
+	try {
9
+		cppcms::service app(argc,argv);
10
+		app.applications_pool().mount(cppcms::applications_factory<apps::wiki>());
11
+		app.run();
12
+	}
13
+	catch(std::exception const &e) {
14
+		BOOSTER_ERROR("wikipp") << e.what() ;
15
+		std::cerr<<e.what()<<std::endl;
16
+		return 1;
17
+	}
18
+	return 0;
19
+}

+ 72
- 0
src/markdown.cpp View File

@@ -0,0 +1,72 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <vector>
4
+#include <stdexcept>
5
+#include "markdown.h"
6
+
7
+extern "C" {
8
+	#include <mkdio.h>
9
+}
10
+
11
+std::string markdown_to_html(char const *str,int len,int flags)
12
+{
13
+	/// It is safe to const cast as mkd_string does not 
14
+	/// alter original string
15
+	MMIOT *doc = mkd_string(const_cast<char *>(str),len,flags);
16
+	if(!doc) {
17
+		throw std::runtime_error("Failed to read document");
18
+	}
19
+
20
+	mkd_compile(doc,flags);
21
+	
22
+	std::string result;
23
+	result.reserve(len);
24
+	char *content_ptr = 0;
25
+	int content_size = 0;
26
+	char *toc_ptr = 0;
27
+	int toc_size = 0;
28
+
29
+	content_size = mkd_document(doc,&content_ptr);
30
+	if(flags & mkd::toc) {
31
+		toc_size = mkd_toc(doc,&toc_ptr);
32
+		result.assign(toc_ptr,toc_size);
33
+	}
34
+	result.append(content_ptr,content_size);
35
+	free(toc_ptr);
36
+	mkd_cleanup(doc);
37
+
38
+	return result;
39
+}
40
+
41
+
42
+std::string markdown_format_for_highlighting(std::string const &input,std::string const &html_class)
43
+{
44
+	enum { part_a , part_b } state = part_a;
45
+	std::string repla = "<pre name=\"code\" class=\"" + html_class + "\">";
46
+	std::string replb = "</pre>";
47
+	std::string origa="<pre><code>";
48
+	std::string origb="</code></pre>";
49
+	std::string result;
50
+	result.reserve(input.size());
51
+	size_t pos = 0;
52
+	while(pos < input.size()) {
53
+		std::string const &orig = state == part_a ? origa : origb;
54
+		std::string const &repl = state == part_a ? repla : replb;
55
+		size_t next = input.find(orig,pos);
56
+		if(next == std::string::npos)
57
+			next = input.size();
58
+		result.append(input.data() + pos, next - pos);
59
+		if(next < input.size()) {
60
+			result.append(repl);
61
+			pos = next + orig.size();
62
+			if(state == part_a)
63
+				state = part_b;
64
+			else
65
+				state = part_a;
66
+		}
67
+		else {
68
+			pos = next;
69
+		}
70
+	}
71
+	return result;
72
+}

+ 33
- 0
src/markdown.h View File

@@ -0,0 +1,33 @@
1
+#ifndef WIKIPP_MARKDOWN_H
2
+#define WIKIPP_MARKDOWN_H
3
+
4
+#include <string>
5
+
6
+namespace mkd {
7
+	static const int no_links     = 0x0001;  // don't do link processing, block <a> tags  
8
+	static const int no_image     = 0x0002;  // don't do image processing, block <img> 
9
+	static const int no_pants     = 0x0004;  // don't run smartypants() 
10
+	static const int no_html      = 0x0008;  // don't allow raw html through at all 
11
+	static const int strict       = 0x0010;  // disable superscript, relaxed_emphasis 
12
+	static const int tagtext      = 0x0020;  // process text inside an html tag; no
13
+	                                         // <em>, no <bold>, no html or [] expansion 
14
+	static const int no_ext       = 0x0040;  // don't allow pseudo-protocols 
15
+	static const int cdata        = 0x0080;  // generate code for xml ![cdata[...]] 
16
+	static const int no_tables    = 0x0400;  // disallow tables 
17
+	static const int toc          = 0x1000;  // do table-of-contents processing 
18
+	static const int compat       = 0x2000;  // compatability with markdowntest_1.0 
19
+	static const int autolink     = 0x4000;  // make http://foo.com link even without <>s 
20
+	static const int safelink     = 0x8000;  // paranoid check for link protocol 
21
+	static const int embed        = no_links|no_image|tagtext;
22
+
23
+					  
24
+	static const int no_header    = 0x0100;  // don't process header blocks 
25
+	static const int tabstop      = 0x0200;  // expand tabs to 4 spaces 
26
+};
27
+
28
+std::string markdown_to_html(char const *str,int len,int flags);
29
+std::string markdown_format_for_highlighting(std::string const &,std::string const &html_class);
30
+
31
+#endif
32
+
33
+

+ 143
- 0
src/master.cpp View File

@@ -0,0 +1,143 @@
1
+#include "wiki.h"
2
+#include "master.h"
3
+#include "master_content.h"
4
+#include "markdown.h"
5
+#include <cppcms/localization.h>
6
+#include <cppcms/service.h>
7
+#include <cppcms/xss.h>
8
+
9
+#define _(X) ::cppcms::locale::translate(X)
10
+#define N_(S,P,N)  ::cppcms::locale::translate(S,P,N)
11
+
12
+namespace {
13
+	cppcms::xss::rules const &xss_filter()
14
+	{
15
+		static cppcms::xss::rules r;
16
+		static bool initialized = false;
17
+		if(initialized)
18
+			return r;
19
+		using namespace cppcms::xss;
20
+
21
+		r.html(rules::xhtml_input);
22
+		r.add_tag("ol",rules::opening_and_closing);
23
+		r.add_tag("ul",rules::opening_and_closing);
24
+		r.add_tag("li",rules::opening_and_closing);
25
+		r.add_tag("p",rules::opening_and_closing);
26
+		r.add_property("p","style",booster::regex("\\s*text-align\\s*:\\s*(center|left|right)\\s*;?"));
27
+		r.add_tag("b",rules::opening_and_closing);
28
+		r.add_tag("i",rules::opening_and_closing);
29
+		r.add_tag("tt",rules::opening_and_closing);
30
+		r.add_tag("sub",rules::opening_and_closing);
31
+		r.add_tag("sup",rules::opening_and_closing);
32
+		r.add_tag("blockquote",rules::opening_and_closing);
33
+		r.add_tag("strong",rules::opening_and_closing);
34
+		r.add_tag("em",rules::opening_and_closing);
35
+		r.add_tag("h1",rules::opening_and_closing);
36
+		r.add_tag("h2",rules::opening_and_closing);
37
+		r.add_tag("h3",rules::opening_and_closing);
38
+		r.add_tag("h4",rules::opening_and_closing);
39
+		r.add_tag("h5",rules::opening_and_closing);
40
+		r.add_tag("h6",rules::opening_and_closing);
41
+		booster::regex cl_id(".*");
42
+		r.add_property("h1","id",cl_id);
43
+		r.add_property("h2","id",cl_id);
44
+		r.add_property("h3","id",cl_id);
45
+		r.add_property("h4","id",cl_id);
46
+		r.add_property("h5","id",cl_id);
47
+		r.add_property("h6","id",cl_id);
48
+		r.add_tag("span",rules::opening_and_closing);
49
+		r.add_property("span","id",cl_id);
50
+		r.add_tag("code",rules::opening_and_closing);
51
+		r.add_tag("pre",rules::opening_and_closing);
52
+		r.add_property("pre","name",booster::regex("\\w+"));
53
+		r.add_property("pre","class",booster::regex("\\w+"));
54
+		r.add_tag("a",rules::opening_and_closing);
55
+		r.add_uri_property("a","href");
56
+		r.add_tag("hr",rules::stand_alone);
57
+		r.add_tag("br",rules::stand_alone);
58
+		r.add_tag("img",rules::stand_alone);
59
+		r.add_uri_property("img","src");
60
+		r.add_integer_property("img","width");
61
+		r.add_integer_property("img","height");
62
+		r.add_integer_property("img","border");
63
+		r.add_property("img","alt",booster::regex(".*"));
64
+		r.add_tag("table",rules::opening_and_closing);
65
+		r.add_tag("tr",rules::opening_and_closing);
66
+		r.add_tag("th",rules::opening_and_closing);
67
+		r.add_tag("td",rules::opening_and_closing);
68
+		r.add_integer_property("table","cellpadding");
69
+		r.add_integer_property("table","cellspacing");
70
+		r.add_integer_property("table","border");
71
+		r.add_tag("center",rules::opening_and_closing);
72
+		r.add_entity("nbsp");
73
+		r.encoding("UTF-8");
74
+		r.comments_allowed(true);
75
+
76
+		initialized = true;
77
+		return r;
78
+	}
79
+
80
+	struct init_it { init_it() { xss_filter(); } } instance;
81
+}
82
+
83
+
84
+std::string mymarkdown(std::string const &s)
85
+{
86
+	int flags = mkd::no_pants;
87
+	if(s.compare(0,10,"<!--toc-->")==0) {
88
+		flags |= mkd::toc;
89
+	}
90
+	std::string html = markdown_format_for_highlighting(markdown_to_html(s.c_str(),s.size(),flags),"cpp");
91
+	return cppcms::xss::filter(html,xss_filter(),cppcms::xss::escape_invalid);
92
+}
93
+
94
+namespace apps {
95
+
96
+master::master(wiki &_w) : 
97
+	application(_w.service()),
98
+	wi(_w),
99
+	locale_name(wi.locale_name)
100
+{
101
+	conn = wi.conn;
102
+	cppcms::json::object langs=settings().get("wikipp.languages",cppcms::json::object());
103
+	for(cppcms::json::object::const_iterator p=langs.begin(),e=langs.end();p!=e;++p) {
104
+		std::string lname;
105
+		if(p->first=="en")
106
+			lname="English";
107
+		else {
108
+			/// Translate as the target language
109
+			/// for fr gettext("LANG")="Francis"
110
+			lname=_("LANG").str(service().generator().generate(p->second.str()));
111
+			if(lname=="LANG") {
112
+				lname=p->first;
113
+			}
114
+		}
115
+		languages[lname]=settings().get<std::string>("wikipp.script") +"/"+ p->first.str();
116
+	}
117
+	media=settings().get<std::string>("wikipp.media");
118
+	syntax_highlighter=settings().get("wikipp.syntax_highlighter","");
119
+	cookie_prefix=settings().get("session.cookies.prefix","cppcms_session")+"_";
120
+}
121
+
122
+void master::ini(content::master &c)
123
+{
124
+	wi.options.load();
125
+	c.markdown = mymarkdown;
126
+	c.media=media;
127
+	c.syntax_highlighter=syntax_highlighter;
128
+	c.cookie_prefix=cookie_prefix;
129
+	c.main_link=wi.page.default_page_url();
130
+	c.main_local=wi.page.default_page_url(locale_name);
131
+	c.toc=wi.index.index_url();
132
+	c.changes=wi.index.changes_url();
133
+	c.login_link=wi.users.login_url();
134
+	c.wiki_title=wi.options.local.title;
135
+	c.about=wi.options.local.about;
136
+	c.copyright=wi.options.local.copyright;
137
+	c.contact=wi.options.global.contact;
138
+	c.edit_options=wi.options.edit_url();
139
+	c.languages=languages;
140
+}
141
+
142
+
143
+}

+ 33
- 0
src/master.h View File

@@ -0,0 +1,33 @@
1
+#ifndef MASTER_H
2
+#define MASTER_H
3
+
4
+#include <cppcms/application.h>
5
+#include <map>
6
+
7
+namespace content { class master; }
8
+namespace cppdb { class session; }
9
+namespace apps {
10
+
11
+class wiki;
12
+
13
+class master : public cppcms::application {
14
+protected:
15
+	wiki &wi;
16
+	std::string conn;
17
+	std::string &locale_name;
18
+	std::map<std::string,std::string> languages;
19
+public:
20
+	master(wiki &w);
21
+	void ini(content::master &);
22
+private:
23
+	std::string media;
24
+	std::string syntax_highlighter;
25
+	std::string cookie_prefix;
26
+};
27
+
28
+} // namespace wiki
29
+
30
+
31
+#endif
32
+
33
+

+ 31
- 0
src/master_content.h View File

@@ -0,0 +1,31 @@
1
+#ifndef MASTER_DATA_H
2
+#define MASTER_DATA_H
3
+#include <cppcms/view.h>
4
+#include <cppcms/form.h>
5
+#include <booster/function.h>
6
+#include <string>
7
+
8
+namespace apps { class wiki; }
9
+
10
+namespace content {
11
+
12
+struct master : public cppcms::base_content {
13
+	std::string media;
14
+	std::string syntax_highlighter;
15
+	std::string cookie_prefix;
16
+	std::string main_link;
17
+	std::string main_local;
18
+	std::string login_link;
19
+	std::string toc;
20
+	std::string changes;
21
+	std::string edit_options;
22
+	std::string contact;
23
+	std::string wiki_title,about,copyright;
24
+	std::map<std::string,std::string> languages;
25
+	booster::function<std::string(std::string const &)> markdown;
26
+};
27
+
28
+}
29
+
30
+
31
+#endif

+ 83
- 0
src/migrate.cpp View File

@@ -0,0 +1,83 @@
1
+#include <cppdb/frontend.h>
2
+#include <iostream>
3
+
4
+int main(int argc,char **argv)
5
+{
6
+	if(argc!=3) {
7
+		std::cerr <<	"Wikipp database migration utility - allows to convert database from one\n"
8
+				"engine to another. It supports: postgresql, mysql, sqlite3\n"
9
+				"\n"
10
+				"To use, create a new database using provided sql scripts and then run\n"
11
+				"$ wikipp_migrate source_connection_string target_connection_string\n" 
12
+				<< std::endl;
13
+		return 1;
14
+	}
15
+
16
+	std::string cs_src = argv[1];
17
+	std::string cs_tgt = argv[2];
18
+	try {
19
+		using namespace cppdb;
20
+		session src(cs_src);
21
+		session tgt(cs_tgt);
22
+		transaction tr_src(src);
23
+		transaction tr_tgt(tgt);
24
+
25
+		result r;
26
+		statement st;
27
+		r = src << "SELECT lang,name,value FROM options";
28
+		st = tgt<<"INSERT into options(lang,name,value) values(?,?,?)";
29
+		while(r.next()) {
30
+			std::string l,n,v;
31
+			r>>l>>n>>v;
32
+			st << l << n << v;
33
+			st.exec();
34
+			st.reset();
35
+		}
36
+
37
+		r = src << "SELECT id, username, password FROM users";
38
+		st = tgt << "INSERT into users(id,username,password) values(?,?,?)";
39
+		while(r.next()) {
40
+			std::string id,user,pass;
41
+			r >> id >> user >> pass;
42
+			st << id << user << pass;
43
+			st.exec();
44
+			st.reset();
45
+		}
46
+
47
+		r = src << "SELECT id, lang, slug, title, content, sidebar, users_only FROM pages";
48
+		st = tgt << "INSERT into pages(id, lang, slug, title, content, sidebar, users_only) values(?,?,?,?,?,?,?)";
49
+		while(r.next()) {
50
+			long long id;
51
+			int users_only;
52
+			std::string lang, slug, title, content, sidebar;
53
+			r >> id >> lang >> slug >> title >> content >> sidebar >> users_only;
54
+			st << id << lang << slug << title << content << sidebar << users_only;
55
+			st.exec();
56
+			st.reset();
57
+		}
58
+		r = src << "SELECT id, version, created, author, title, content, sidebar FROM history ";
59
+		st = tgt << "INSERT INTO history(id, version, created, author, title, content, sidebar) VALUES(?,?,?,?,?,?,?)";
60
+		while(r.next()) {
61
+			long long id,version;
62
+			std::tm created;
63
+			std::string a,t,c,side;
64
+			r >> id >> version >> created >> a >> t >> c >> side;
65
+			st << id << version << created << a << t << c << side;
66
+			st.exec();
67
+			st.reset();
68
+		}
69
+		if(tgt.engine()=="postgresql") {
70
+			tgt<<"SELECT setval('users_id_seq',(SELECT max(id) FROM users))" << row;
71
+			tgt<<"SELECT setval('pages_id_seq',(SELECT max(id) FROM pages))" << row;
72
+		}
73
+
74
+		tr_src.commit();
75
+		tr_tgt.commit();
76
+
77
+	}
78
+	catch(std::exception const &e) {
79
+		std::cerr <<"Failed " << e.what() << std::endl;
80
+		return 1;
81
+	}
82
+	return 0;
83
+}

+ 180
- 0
src/options.cpp View File

@@ -0,0 +1,180 @@
1
+#include "options.h"
2
+#include "wiki.h"
3
+#include "options_content.h"
4
+#include <cppcms/localization.h>
5
+#include <cppcms/url_dispatcher.h>
6
+#include <cppcms/cache_interface.h>
7
+#include <cppcms/serialization.h>
8
+
9
+#define _(X) ::cppcms::locale::translate(X)
10
+
11
+namespace content {
12
+options_form::options_form()
13
+{
14
+	users_only.message(_("Users Only"));
15
+	contact_mail.message(_("Contact e-mail"));
16
+	wiki_title.message(_("Wiki Title"));
17
+	about.message(_("About Wiki"));
18
+	copyright.message(_("Copyright String"));
19
+	submit.value(_("Submit"));
20
+	add(users_only);
21
+	add(contact_mail);
22
+	add(wiki_title);
23
+	add(copyright);
24
+	add(about);
25
+	add(submit);
26
+	wiki_title.non_empty();
27
+	copyright.non_empty();
28
+	contact_mail.non_empty();
29
+	about.non_empty();
30
+	about.rows(10);
31
+	about.cols(40);
32
+	users_only.help(_("Disable creation of new articles by visitors"));
33
+}
34
+
35
+} // namespace content
36
+
37
+namespace apps {
38
+
39
+void global_options::serialize(cppcms::archive &a)
40
+{
41
+	a & users_only_edit & contact;
42
+}
43
+
44
+void locale_options::serialize(cppcms::archive &a)
45
+{
46
+	a & title & about & copyright ;
47
+}
48
+
49
+
50
+options::options(wiki &w):
51
+	master(w)
52
+{
53
+	wi.dispatcher().assign("^/options/?$",&options::edit,this);
54
+	reset();
55
+}
56
+
57
+void options::reset()
58
+{
59
+	loaded=false;
60
+}
61
+
62
+std::string options::edit_url()
63
+{
64
+	return wi.root()+"/options/";
65
+}
66
+
67
+void options::load()
68
+{
69
+	cppdb::session sql(conn);
70
+	if(loaded)
71
+		return;
72
+	global.users_only_edit=0;
73
+	global.contact.clear();
74
+	local.about.clear();
75
+	local.title.clear();
76
+	local.copyright.clear();
77
+	if(!cache().fetch_data("global_ops",global)) 
78
+	{
79
+		cppdb::result r;
80
+		r=sql<<	"SELECT name,value FROM options "
81
+			"WHERE	lang='global' ";
82
+		while(r.next()) {
83
+			std::string n,v;
84
+			r >> n >> v;
85
+			if(n=="users_only_edit")
86
+				global.users_only_edit=atoi(v.c_str());
87
+			else if(n=="contact")
88
+				global.contact=v;
89
+		}
90
+		if(global.contact.empty())
91
+			global.contact="no@mail";
92
+		cache().store_data("global_ops",global);
93
+	}
94
+	if(cache().fetch_data("local_ops:"+locale_name,local))
95
+		return;
96
+	cppdb::result r;
97
+	r=sql<<	"SELECT value,name FROM options "
98
+		"WHERE  lang=?" << locale_name;
99
+	while(r.next()) {
100
+		std::string v,n;
101
+		r>>v>>n;
102
+		if(n=="title")
103
+			local.title=v;
104
+		else if(n=="about")
105
+			local.about=v;
106
+		else if(n=="copyright")
107
+			local.copyright=v;
108
+	}
109
+	if(local.title.empty())
110
+		local.title=cppcms::locale::gettext("Wiki++ - CppCMS Wiki",context().locale());
111
+	if(local.about.empty())
112
+		local.about=
113
+			cppcms::locale::gettext("## About\n"
114
+				"\n"
115
+				"Wiki++ is a wiki engine powered by\n"
116
+				"[CppCMS](http://cppcms.sf.net/) web development framework.\n",context().locale());
117
+	if(local.copyright.empty())
118
+		local.copyright=cppcms::locale::gettext("(C) All Rights Reserved",context().locale());
119
+	cache().store_data("local_ops:"+locale_name,local);
120
+	loaded=true;
121
+}
122
+
123
+
124
+void options::save()
125
+{
126
+	cppdb::session sql(conn);
127
+	cppdb::transaction guard(sql);
128
+
129
+	sql<<	"DELETE FROM options "
130
+		"WHERE lang='global' OR lang=?" 
131
+		<< locale_name << cppdb::exec;
132
+	sql<<	"INSERT INTO options(value,name,lang) "
133
+		"VALUES(?,'users_only_edit','global')" <<  global.users_only_edit << cppdb::exec;
134
+	sql<<	"INSERT INTO options(value,name,lang) "
135
+		"VALUES(?,'contact','global')" <<  global.contact << cppdb::exec;
136
+	sql<<	"INSERT INTO options(value,name,lang) "
137
+		"VALUES(?,'title',?)" <<  local.title << locale_name << cppdb::exec;
138
+	sql<<	"INSERT INTO options(value,name,lang) "
139
+		"VALUES(?,'about',?)" << local.about << locale_name << cppdb::exec;
140
+	sql<<	"INSERT INTO options(value,name,lang) "
141
+		"VALUES(?,'copyright',?)" << local.copyright << locale_name << cppdb::exec;
142
+	cache().rise("global_ops");
143
+	cache().rise("local_ops:"+locale_name);
144
+	guard.commit();
145
+	reset();
146
+}
147
+
148
+void options::edit()
149
+{
150
+	if(!wi.users.auth()) {
151
+		wi.users.error_forbidden();
152
+		return;
153
+	}
154
+	content::edit_options c;
155
+	if(request().request_method()=="POST") {
156
+		c.form.load(context());
157
+		if(c.form.validate()) {
158
+			global.users_only_edit=c.form.users_only.value();
159
+			global.contact=c.form.contact_mail.value();
160
+			local.title=c.form.wiki_title.value();
161
+			local.copyright=c.form.copyright.value();
162
+			local.about=c.form.about.value();
163
+			save();
164
+		}
165
+	}
166
+	else {
167
+		load();
168
+		c.form.users_only.value(global.users_only_edit);
169
+		c.form.wiki_title.value(local.title);
170
+		c.form.copyright.value(local.copyright);
171
+		c.form.about.value(local.about);
172
+		c.form.contact_mail.value(global.contact);
173
+	}
174
+	ini(c);
175
+	render("edit_options",c);
176
+}
177
+
178
+
179
+}
180
+

+ 41
- 0
src/options.h View File

@@ -0,0 +1,41 @@
1
+#ifndef OPTIONS_H
2
+#define OPTIONS_H
3
+#include "master.h"
4
+#include <cppcms/json.h>
5
+#include <cppcms/serialization_classes.h>
6
+
7
+namespace apps {
8
+
9
+struct global_options : public cppcms::serializable {
10
+	int users_only_edit;
11
+	std::string contact;
12
+	void serialize(cppcms::archive &a);
13
+};
14
+
15
+struct locale_options : public cppcms::serializable{
16
+	std::string title;
17
+	std::string about;
18
+	std::string copyright;
19
+	void serialize(cppcms::archive &a);
20
+};
21
+
22
+
23
+
24
+
25
+class options : public master {
26
+	bool loaded;
27
+protected:
28
+	void edit();
29
+public:
30
+	void reset();
31
+	options(apps::wiki &);
32
+	void load();
33
+	void save();
34
+	std::string edit_url();
35
+	global_options global;
36
+	locale_options  local;
37
+};
38
+
39
+} // apps;
40
+
41
+#endif

+ 27
- 0
src/options_content.h View File

@@ -0,0 +1,27 @@
1
+#ifndef OPTIONS_CONTENT_H
2
+#define OPTIONS_CONTENT_H
3
+
4
+#include "master_content.h"
5
+
6
+namespace content {
7
+
8
+struct options_form : cppcms::form {
9
+	cppcms::widgets::checkbox users_only;
10
+	cppcms::widgets::text contact_mail;
11
+	cppcms::widgets::text wiki_title;
12
+	cppcms::widgets::textarea about;
13
+	cppcms::widgets::text copyright;
14
+	cppcms::widgets::submit submit;
15
+	options_form();
16
+};
17
+
18
+
19
+struct edit_options:  public master {
20
+	options_form form;
21
+};
22
+
23
+
24
+} // namespace content
25
+
26
+#endif
27
+

+ 432
- 0
src/page.cpp View File

@@ -0,0 +1,432 @@
1
+#include "page.h"
2
+#include "page_content.h"
3
+#include "wiki.h"
4
+#include "diff.h"
5
+
6
+#include <booster/posix_time.h>
7
+#include <cppcms/url_dispatcher.h>
8
+#include <cppcms/cache_interface.h>
9
+
10
+#define _(X) ::cppcms::locale::translate(X)
11
+
12
+namespace content { 
13
+// Page content
14
+page_form::page_form(apps::wiki *_w):
15
+	w(_w)
16
+{
17
+	title.message(_("Title"));
18
+	content.message(_("Content"));
19
+	sidebar.message(_("Sidebar"));
20
+	save.value(_("Save"));
21
+	save_cont.value(_("Save and Continue"));
22
+	preview.value(_("Preview"));
23
+	fields.add(title);
24
+	fields.add(content);
25
+	fields.add(sidebar);
26
+	buttons.add(save);
27
+	buttons.add(save_cont);
28
+	buttons.add(preview);
29
+	buttons.add(users_only);
30
+	add(fields);
31
+	add(buttons);
32
+	users_only.help(_("Disable editing by visitors"));
33
+	users_only.error_message(_("Please Login"));
34
+	title.non_empty();
35
+	content.non_empty();
36
+	content.rows(25);
37
+	content.cols(60);
38
+	sidebar.rows(10);
39
+	sidebar.cols(60);
40
+}
41
+
42
+bool page_form::validate()
43
+{
44
+	bool res=form::validate();
45
+	if(users_only.value() && !w->users.auth()) {
46
+		users_only.valid(false);
47
+		users_only.value(false);
48
+		return false;
49
+	}
50
+	return res;
51
+}
52
+
53
+} // namespace content
54
+
55
+namespace apps {
56
+
57
+page::page(wiki &w):
58
+	master(w)
59
+{
60
+	wi.dispatcher().assign("^/page/(\\w+)/version/(\\d+)$",&page::display_ver,this,1,2);
61
+	wi.dispatcher().assign("^/page/(\\w+)/?$",&page::display,this,1);
62
+	wi.dispatcher().assign("^/page/(\\w+)/edit(/version/(\\d+))?$",&page::edit,this,1,3);
63
+	wi.dispatcher().assign("^/page/(\\w+)/history(/|/(\\d+))?$",&page::history,this,1,3);
64
+	wi.dispatcher().assign("^/page/(\\w+)/diff/(\\d+)vs(\\d+)/?$",&page::diff,this,1,2,3);
65
+}
66
+
67
+std::string page::diff_url(int v1,int v2,std::string l,std::string s)
68
+{
69
+	if(l.empty()) l=locale_name;
70
+	if(s.empty()) s=slug;
71
+	return wi.root(l) + 
72
+		(booster::locale::format("/page/{1}/diff/{2}vs{3}") % s % v1 % v2).str();
73
+}
74
+
75
+std::string page::page_url(std::string l,std::string s)
76
+{
77
+	if(l.empty()) l=locale_name;
78
+	if(s.empty()) s=slug;
79
+	return wi.root(l)+"/page/"+s;
80
+}
81
+
82
+std::string page::page_version_url(int ver,std::string l,std::string s)
83
+{
84
+	if(l.empty()) l=locale_name;
85
+	if(s.empty()) s=slug;
86
+	return wi.root(l)+
87
+		(booster::locale::format("/page/{1}/version/{2}") % s % ver).str();
88
+}
89
+std::string page::edit_url()
90
+{
91
+	return wi.root()+"/page/"+slug+"/edit";
92
+}
93
+std::string page::edit_version_url(int ver)
94
+{
95
+	return (booster::locale::format(edit_url()+"/version/{1}") % ver).str();
96
+}
97
+std::string page::history_url(int n)
98
+{
99
+	std::string u=wi.root()+"/page/"+slug+"/history/";
100
+	if(n)
101
+		u+=(booster::locale::format("{1}") % n).str();
102
+	return u;
103
+}
104
+
105
+void page::diff(std::string slug,std::string sv1,std::string sv2)
106
+{
107
+	int v1=atoi(sv1.c_str()), v2=atoi(sv2.c_str());
108
+	this->slug=slug;
109
+	cppdb::session sql(conn);
110
+	cppdb::result r;
111
+	content::diff c;
112
+	c.v1=v1;
113
+	c.v2=v2;
114
+	c.edit_v1=edit_version_url(v1);
115
+	c.edit_v2=edit_version_url(v2);
116
+	r=sql<<	"SELECT version,history.title,history.content,history.sidebar,pages.title FROM pages "
117
+		"JOIN history ON pages.id=history.id "
118
+		"WHERE lang=? AND slug=? AND version IN (?,?) " << locale_name << slug << v1 << v2;
119
+	
120
+	std::string t1,c1,s1,t2,c2,s2;
121
+	int count=0;
122
+	while(r.next()) {
123
+		int ver;
124
+		r>>ver;
125
+		if(ver==v1) {
126
+			r>>t1>>c1>>s1>>c.title;
127
+		}
128
+		else {
129
+			r>>t2>>c2>>s2;
130
+		}
131
+		count++;
132
+	}
133
+	if(count != 2) {
134
+		c.no_versions=true;
135
+		master::ini(c);
136
+		render("diff",c);
137
+		return;
138
+	}
139
+	if(t1!=t2) {
140
+		c.title_diff=true;
141
+		c.title_1=t1;
142
+		c.title_2=t2;
143
+	}
144
+	else {
145
+		c.title=t1;
146
+	}
147
+	if(c1!=c2) {
148
+		c.content_diff=true;
149
+		std::vector<std::string> X=split(c1);
150
+		std::vector<std::string> Y=split(c2);
151
+		diff::diff(X,Y,c.content_diff_content);
152
+	}
153
+	if(s1!=s2) {
154
+		c.sidebar_diff=true;
155
+		std::vector<std::string> X=split(s1);
156
+		std::vector<std::string> Y=split(s2);
157
+		diff::diff(X,Y,c.sidebar_diff_content);
158
+	}
159
+	if(t1==t2 && c1==c2 && s1==s2) 
160
+		c.no_diff=true;
161
+	master::ini(c);
162
+	render("diff",c);
163
+}
164
+
165
+void page::history(std::string slug,std::string page)
166
+{
167
+	this->slug=slug;
168
+	unsigned const vers=10;
169
+	int offset;
170
+	content::history c;
171
+	master::ini(c);
172
+	if(page.empty())
173
+		offset=0;
174
+	else
175
+		offset=atoi(page.c_str());
176
+
177
+	cppdb::session sql(conn);
178
+	cppdb::result r;
179
+	r=sql<<	"SELECT title,id FROM pages "
180
+		"WHERE pages.lang=? AND pages.slug=? " << locale_name << slug << cppdb::row;
181
+	if(r.empty()) {
182
+		redirect(locale_name);
183
+		return;
184
+	}
185
+	int id;
186
+	r>>c.title>>id;
187
+	r=sql<<	"SELECT created,version,author FROM history "
188
+		"WHERE id=? "
189
+		"ORDER BY version DESC "
190
+		"LIMIT ? "
191
+		"OFFSET ?"
192
+		<<id << vers+1 << offset*vers;
193
+
194
+	c.hist.reserve(vers);
195
+	for(unsigned i=0;r.next() && i<vers;i++) {
196
+		int ver;
197
+		c.hist.resize(i+1);
198
+		std::tm update = std::tm();
199
+		r>> update >> ver >> c.hist[i].author ;
200
+		c.hist[i].update = mktime(&update);
201
+		c.hist[i].version=ver;
202
+		c.hist[i].show_url=page_version_url(ver);
203
+		c.hist[i].edit_url=edit_version_url(ver);
204
+		if(ver>1)
205
+			c.hist[i].diff_url=diff_url(ver-1,ver);
206
+	}
207
+	
208
+	if(r.next()) {
209
+		c.page=history_url(offset+1);
210
+	}
211
+
212
+	c.page_link=page_url();
213
+	render("history",c);
214
+}
215
+
216
+
217
+void page::display(std::string slug)
218
+{
219
+	this->slug=slug;
220
+	std::string key="article_"+locale_name+":"+slug;
221
+	if(cache().fetch_page(key))
222
+		return;
223
+	content::page c;
224
+
225
+	cppdb::session sql(conn);
226
+	cppdb::result r;
227
+	r=sql<<	"SELECT title,content,sidebar FROM pages WHERE lang=? AND slug=?"
228
+		<<locale_name << slug << cppdb::row;
229
+	if(r.empty()) {
230
+		std::string redirect=edit_url();
231
+		std::cerr << " Page " << redirect << std::endl;
232
+		response().set_redirect_header(redirect);
233
+		return;
234
+	}
235
+	ini(c);
236
+	r >> c.title >> c.content >> c.sidebar;
237
+	render("page",c);
238
+	cache().store_page(key);
239
+}
240
+
241
+void page::ini(content::page &c)
242
+{
243
+	master::ini(c);
244
+	c.edit_link=edit_url();
245
+	c.history_link=history_url();
246
+}
247
+
248
+void page::edit(std::string slug,std::string version)
249
+{
250
+	this->slug=slug;
251
+	content::edit_page c(&wi);
252
+	if(request().request_method()=="POST") {
253
+		if(!edit_on_post(c))
254
+			return;
255
+	}
256
+	else {
257
+		if(version.empty()) {
258
+			c.new_page=!load(c.form);
259
+			if(c.new_page) {
260
+				wi.options.load();
261
+				c.form.users_only.value(wi.options.global.users_only_edit);
262
+			}
263
+		}
264
+		else {
265
+			int ver=atoi(version.c_str());
266
+			if(!load_history(ver,c.form)) {
267
+				redirect(locale_name,slug);
268
+				return;
269
+			}
270
+		}
271
+		if(c.form.users_only.value() && !wi.users.auth()) {
272
+			wi.users.error_forbidden();
273
+		}
274
+	}
275
+	ini(c);
276
+	c.back=page_url();
277
+	c.submit=edit_url();
278
+	render("edit_page",c);
279
+}
280
+
281
+bool page::load(content::page_form &form)
282
+{
283
+	cppdb::session sql(conn);
284
+	cppdb::result r;
285
+	r=sql<<	"SELECT title,content,sidebar,users_only "
286
+		"FROM pages WHERE lang=? AND slug=?" << locale_name << slug << cppdb::row;
287
+	if(!r.empty()) {
288
+		std::string title,content,sidebar;
289
+		int users_only;
290
+		r >> title >> content >> sidebar >> users_only;
291
+		form.title.value(title);
292
+		form.content.value(content);
293
+		form.sidebar.value(sidebar);
294
+		form.users_only.value(users_only);
295
+		return true;
296
+	}
297
+	wi.options.load();
298
+	form.users_only.set(wi.options.global.users_only_edit);
299
+	return false;
300
+}
301
+
302
+void page::redirect(std::string loc,std::string slug)
303
+{
304
+	std::string redirect=page_url(loc,slug);
305
+	response().set_redirect_header(redirect);
306
+}
307
+
308
+void page::save(int id,content::page_form &form,cppdb::session &sql)
309
+{
310
+	std::tm t = booster::ptime::local_time(booster::ptime::now());
311
+	wi.users.auth();
312
+	if(id!=-1) {
313
+		sql<<	"UPDATE pages SET content=?,title=?,sidebar=?,users_only=? "
314
+			"WHERE lang=? AND slug=?"
315
+				<< form.content.value() << form.title.value() 
316
+				<< form.sidebar.value() << form.users_only.value() 
317
+				<< locale_name << slug << cppdb::exec;
318
+	}
319
+	else {
320
+		cppdb::statement s;
321
+		s=sql<<	"INSERT INTO pages(lang,slug,title,content,sidebar,users_only) "
322
+			"VALUES(?,?,?,?,?,?)"
323
+			<< locale_name << slug
324
+			<< form.title.value()
325
+			<< form.content.value()
326
+			<< form.sidebar.value()
327
+			<< form.users_only.value();
328
+		s.exec();
329
+		id=s.sequence_last("pages_id_seq");
330
+	}
331
+	sql<<	"INSERT INTO history(id,version,created,title,content,sidebar,author) "
332
+		"SELECT ?,"
333
+		"	(SELECT COALESCE(MAX(version),0)+1 FROM history WHERE id=?),"
334
+		"	?,?,?,?,?"
335
+			<< id << id << t 
336
+			<< form.title.value()
337
+			<< form.content.value()
338
+			<< form.sidebar.value()
339
+			<< wi.users.username 
340
+			<< cppdb::exec;
341
+}
342
+
343
+
344
+bool page::edit_on_post(content::edit_page &c)
345
+{
346
+	wi.options.load();
347
+	
348
+	cppdb::session sql(conn);
349
+	cppdb::transaction tr(sql);
350
+	cppdb::result r;
351
+	r=sql<<	"SELECT id,users_only FROM pages WHERE lang=? and slug=?" << locale_name << slug << cppdb::row;
352
+	int id=-1,users_only=wi.options.global.users_only_edit;
353
+	if(!r.empty()) {
354
+		r>>id>>users_only;
355
+	}
356
+	r.clear();
357
+
358
+	if(users_only && !wi.users.auth()) {
359
+		wi.users.error_forbidden();
360
+		return false;
361
+	}
362
+	c.form.load(context());
363
+	if(c.form.validate()) {
364
+		if(c.form.save.value() || c.form.save_cont.value()) {
365
+			save(id,c.form,sql);
366
+			cache().rise("article_"+locale_name+":"+slug);
367
+		}
368
+		if(c.form.save.value()) {
369
+			redirect(locale_name,slug);
370
+			tr.commit();
371
+			return false;
372
+		}
373
+		if(c.form.preview.value()) {
374
+			c.title=c.form.title.value();
375
+			c.content=c.form.content.value();
376
+			c.sidebar=c.form.sidebar.value();
377
+		}
378
+	}
379
+	tr.commit();
380
+	return true;
381
+}
382
+
383
+bool page::load_history(int ver,content::page_form &form)
384
+{
385
+	cppdb::session sql(conn);
386
+	cppdb::result r;
387
+	r=sql<<	"SELECT history.title,history.content,history.sidebar,pages.users_only "
388
+		"FROM pages "
389
+		"JOIN history ON pages.id=history.id "
390
+		"WHERE pages.lang=? AND pages.slug=? AND history.version=?"
391
+		<<locale_name<<slug<<ver<<cppdb::row;
392
+	if(!r.empty()) {
393
+		std::string title,content,sidebar;
394
+		int uonly;
395
+		r >> title >> content >> sidebar >> uonly;
396
+		form.title.value(title);
397
+		form.content.value(content);
398
+		form.sidebar.value(sidebar);
399
+		form.users_only.value(uonly);
400
+		return true;
401
+	}
402
+	return false;
403
+}
404
+
405
+void page::display_ver(std::string slug,std::string sid)
406
+{
407
+	this->slug=slug;
408
+	content::page_hist c;
409
+	int id=atoi(sid.c_str());
410
+	cppdb::result r;
411
+	cppdb::session sql(conn);
412
+	r=sql<<	"SELECT history.title,history.content,history.sidebar,history.created "
413
+		"FROM pages "
414
+		"JOIN history ON pages.id=history.id "
415
+		"WHERE pages.lang=? AND pages.slug=? AND history.version=?"
416
+			<<locale_name << slug << id << cppdb::row;
417
+	if(!r.empty()) {
418
+		redirect(locale_name,slug);
419
+		return;
420
+	}
421
+	std::tm date;
422
+	r>>c.title>>c.content>>c.sidebar>>date;
423
+	c.date = mktime(&date);
424
+	c.version=id;
425
+	c.rollback=edit_version_url(id);
426
+	ini(c);
427
+	render("page_hist",c);
428
+}
429
+
430
+}
431
+
432
+

+ 45
- 0
src/page.h View File

@@ -0,0 +1,45 @@
1
+#ifndef PAGE_H
2
+#define PAGE_H
3
+
4
+#include "master.h"
5
+#include <string>
6
+
7
+namespace content { 
8
+	class page;
9
+	class edit_page;
10
+	class page_form;
11
+}
12
+
13
+namespace apps {
14
+
15
+class page : public master {
16
+	void save(int id,content::page_form &,cppdb::session &sql);
17
+	bool load(content::page_form &);
18
+	bool edit_on_post(content::edit_page &);
19
+	bool load_history(int,content::page_form &);
20
+protected:
21
+	std::string slug;
22
+	void ini(content::page &);
23
+	void display(std::string slug);
24
+	void history(std::string slug,std::string page);
25
+	void display_ver(std::string slug,std::string sid);
26
+	void edit(std::string slug,std::string version);
27
+	void diff(std::string slug,std::string v1,std::string v2);
28
+
29
+	std::string edit_url();
30
+	std::string edit_version_url(int ver);
31
+	std::string history_url(int n=0);
32
+public:
33
+	page(wiki &w);
34
+	std::string diff_url(int v1,int v2,std::string lang="",std::string s="");
35
+	std::string page_url(std::string l="",std::string s="");
36
+	std::string page_version_url(int ver,std::string l="",std::string s="");
37
+	std::string default_page_url(std::string l="en",std::string s="main")
38
+		{ return page_url(l,s); }
39
+	void redirect(std::string locale="en",std::string slug="main");
40
+};
41
+
42
+}
43
+
44
+
45
+#endif

+ 79
- 0
src/page_content.h View File

@@ -0,0 +1,79 @@
1
+#ifndef PAGE_CONTENT_H
2
+#define PAGE_CONTENT_H
3
+
4
+#include "master_content.h"
5
+
6
+namespace content {
7
+
8
+typedef std::list<std::pair<int,std::string> > diff_t;
9
+
10
+struct page_form : public cppcms::form {
11
+	apps::wiki *w;
12
+	cppcms::widgets::text title;
13
+	cppcms::widgets::textarea content;
14
+	cppcms::widgets::textarea sidebar;
15
+	cppcms::widgets::submit save;
16
+	cppcms::widgets::submit save_cont;
17
+	cppcms::widgets::submit preview;
18
+	cppcms::widgets::checkbox users_only;
19
+	cppcms::form fields;
20
+	cppcms::form buttons;
21
+	page_form(apps::wiki *w);
22
+	bool virtual validate();
23
+};
24
+
25
+struct page : public master {
26
+	std::string title,content;
27
+	std::string sidebar;
28
+	std::string edit_link;
29
+	std::string history_link;
30
+};
31
+
32
+struct page_hist: public page {
33
+	int version;
34
+	std::string rollback;
35
+	time_t date;
36
+};
37
+
38
+struct edit_page: public page {
39
+	page_form form;
40
+	bool new_page;
41
+	std::string back;
42
+	std::string submit;
43
+	edit_page(apps::wiki *w) : form(w),new_page(false) {}
44
+};
45
+
46
+struct history : public master {
47
+	struct item {
48
+		time_t update;
49
+		std::string show_url;
50
+		std::string edit_url;
51
+		std::string diff_url;
52
+		int version;
53
+		std::string author;
54
+	};
55
+	std::vector<item> hist;
56
+	std::string page;
57
+	std::string title;
58
+	std::string page_link;
59
+};
60
+
61
+struct diff: public master {
62
+	std::string edit_v1,edit_v2;
63
+	int v1,v2;
64
+	diff_t content_diff_content;
65
+	diff_t sidebar_diff_content;
66
+	std::string title,title_1,title_2;
67
+	bool title_diff,content_diff,sidebar_diff,no_versions,no_diff;
68
+	diff() : 
69
+		title_diff(false),content_diff(false),
70
+		sidebar_diff(false),no_versions(false),
71
+		no_diff(false)
72
+	{
73
+	}
74
+};
75
+
76
+
77
+} // namespace content
78
+
79
+#endif

+ 226
- 0
src/users.cpp View File

@@ -0,0 +1,226 @@
1
+#include "users.h"
2
+#include "wiki.h"
3
+#include "users_content.h"
4
+#include <sys/time.h>
5
+#include <time.h>
6
+
7
+#include <cppcms/url_dispatcher.h>
8
+#include <cppcms/cache_interface.h>
9
+#include <cppcms/session_interface.h>
10
+
11
+#define _(X) ::cppcms::locale::translate(X)
12
+
13
+namespace content {
14
+login_form::login_form(apps::wiki *_w) :
15
+	w(_w)
16
+{
17
+	username.message(_("Username"));
18
+	password.message(_("Password"));
19
+	login.value(_("Login"));
20
+	add(username);
21
+	add(password);
22
+	add(login);
23
+	username.non_empty();
24
+	password.non_empty();
25
+}
26
+
27
+bool login_form::validate()
28
+{
29
+	if(!form::validate())
30
+		return false;
31
+	if(w->users.check_login(username.value(),password.value()))
32
+		return true;
33
+	password.valid(false);
34
+	return false;
35
+}
36
+
37
+
38
+new_user_form::new_user_form(apps::wiki *_w):
39
+	w(_w)
40
+{
41
+	username.message(_("Username"));
42
+	password1.message(_("Password"));
43
+	password2.message(_("Confirm"));
44
+	captcha.message(_("Solve"));
45
+	submit.value(_("Submit"));
46
+	add(username);
47
+	add(password1);
48
+	add(password2);
49
+	add(captcha);
50
+	add(submit);
51
+	username.non_empty();
52
+	password1.non_empty();
53
+	password2.check_equal(password1);
54
+}
55
+
56
+void new_user_form::generate_captcha()
57
+{
58
+	struct timeval tv;
59
+	gettimeofday(&tv,NULL);
60
+	unsigned seed=tv.tv_usec / 1000 % 100;
61
+	int num1=rand_r(&seed) % 10+1;
62
+	int num2=rand_r(&seed) % 10+1;
63
+	int sol=num1+num2;
64
+	captcha.help((booster::locale::format("{1} + {2}") % num1 % num2).str());
65
+	w->session().set("captcha",sol);
66
+	w->session().age(5*60); // at most 5 minutes
67
+}
68
+
69
+bool new_user_form::validate()
70
+{
71
+	if(!form::validate())
72
+		return false;
73
+	
74
+	if(!w->session().is_set("captcha") || captcha.value()!=w->session()["captcha"]) {
75
+		w->session().erase("captcha");
76
+		return false;
77
+	}
78
+	if(w->users.user_exists(username.value())) {
79
+		username.error_message(_("This user exists"));
80
+		username.valid(false);
81
+		return false;
82
+	}
83
+	return true;
84
+}
85
+
86
+
87
+} 
88
+
89
+namespace apps {
90
+
91
+users::users(wiki &w) :	master(w)
92
+{
93
+	wi.dispatcher().assign("^/login/?$",&users::login,this);
94
+	disable_reg=settings().get("wikipp.disable_registration",true);
95
+	if(!disable_reg){
96
+		wi.dispatcher().assign("^/register/?$",&users::new_user,this);
97
+	}
98
+	reset();
99
+}
100
+
101
+void users::new_user()
102
+{
103
+	content::new_user c(&wi);
104
+	if(request().request_method()=="POST") {
105
+		c.form.load(context());
106
+		cppdb::session sql(conn);
107
+		cppdb::transaction tr(sql);
108
+		if(c.form.validate()) {
109
+			sql<<	"INSERT INTO users(username,password) "
110
+				"VALUES(?,?)"
111
+				<< c.form.username.value()
112
+				<< c.form.password1.value()
113
+				<< cppdb::exec;
114
+			tr.commit();
115
+			wi.page.redirect(locale_name);
116
+			session()["username"]=c.form.username.value();
117
+			session().expose("username");
118
+			session().default_age(); // return to default
119
+			return;
120
+		}
121
+		tr.commit();
122
+	}
123
+	c.form.generate_captcha();
124
+	ini(c);
125
+	render("new_user",c);
126
+}
127
+
128
+void users::reset()
129
+{
130
+	auth_done=auth_ok=false;
131
+}
132
+
133
+std::string users::login_url()
134
+{
135
+	return wi.root()+"/login/";
136
+}
137
+
138
+bool users::user_exists(std::string u)
139
+{
140
+	std::string key="user_exists_"+u;
141
+	std::string tmp;
142
+	if(cache().fetch_frame(key,tmp,true)) { // No triggers
143
+		return true;
144
+	}
145
+	cppdb::result r;
146
+	cppdb::session sql(conn);
147
+	r=sql<<"SELECT id FROM users WHERE username=?" << u << cppdb::row;
148
+	if(!r.empty()) {
149
+		cache().store_frame(key,tmp);
150
+		return true;
151
+	}
152
+	return false;
153
+}
154
+
155
+void users::login()
156
+{
157
+	content::login c(&wi);
158
+	if(request().request_method()=="POST") {
159
+		c.form.load(context());
160
+		if(c.form.validate()) {
161
+			wi.page.redirect(locale_name);
162
+			session()["username"]=c.form.username.value();
163
+			session().expose("username");
164
+			return;
165
+		}
166
+	}
167
+	else {
168
+		if(auth()) {
169
+			response().set_redirect_header(request().http_referer());
170
+			session().clear();
171
+			return;
172
+		}
173
+	}
174
+	ini(c);
175
+	if(!disable_reg)
176
+		c.new_user=wi.root()+"/register/";
177
+	render("login",c);
178
+}
179
+
180
+bool users::check_login(std::string u,std::string p)
181
+{
182
+	if(u.empty() || p.empty())
183
+		return false;
184
+	cppdb::result r;
185
+	cppdb::session sql(conn);
186
+	r=sql<<	"SELECT password FROM users "
187
+		"WHERE username=?" << u << cppdb::row;
188
+	if(r.empty()) {
189
+		return false;
190
+	}
191
+	std::string pass;
192
+	r>>pass;
193
+	if(p!=pass)
194
+		return false;
195
+	return true;
196
+}
197
+
198
+bool users::auth()
199
+{
200
+	if(!auth_done)
201
+		do_auth();
202
+	return auth_ok;
203
+}
204
+
205
+void users::do_auth()
206
+{
207
+	if(session().is_set("username") && user_exists(session()["username"])) {
208
+		auth_ok=true;
209
+	}
210
+	else {
211
+		auth_ok=false;
212
+	}
213
+	if(auth_ok)
214
+		username=session()["username"];
215
+	else
216
+		username=request().remote_addr();
217
+	auth_done=true;
218
+}
219
+
220
+void users::error_forbidden()
221
+{
222
+	response().set_redirect_header(login_url());
223
+}
224
+
225
+
226
+}

+ 32
- 0
src/users.h View File

@@ -0,0 +1,32 @@
1
+#ifndef USERS_H
2
+#define USERS_H
3
+
4
+#include "master.h"
5
+
6
+namespace apps {
7
+
8
+class users : public master {
9
+	bool auth_done;
10
+	bool auth_ok;
11
+	bool disable_reg;
12
+
13
+	void login();
14
+	void do_auth();
15
+	void new_user();
16
+public:
17
+	void reset();
18
+	bool user_exists(std::string);
19
+	bool check_login(std::string,std::string);
20
+	bool auth();
21
+	void error_forbidden();
22
+	std::string username;
23
+	std::string login_url();
24
+	users(wiki &);
25
+	
26
+};
27
+
28
+
29
+}
30
+#endif
31
+
32
+

+ 42
- 0
src/users_content.h View File

@@ -0,0 +1,42 @@
1
+#ifndef USERS_CONTENT_H
2
+#define USERS_CONTENT_H
3
+
4
+#include "master_content.h"
5
+
6
+namespace content {
7
+
8
+struct login_form : public cppcms::form {
9
+	apps::wiki *w;
10
+	cppcms::widgets::text username;
11
+	cppcms::widgets::password password;
12
+	cppcms::widgets::submit login;
13
+	login_form(apps::wiki *);
14
+	virtual bool validate();
15
+};
16
+
17
+struct new_user_form : public cppcms::form {
18
+	apps::wiki *w;
19
+	cppcms::widgets::text username;
20
+	cppcms::widgets::password password1;
21
+	cppcms::widgets::password password2;
22
+	cppcms::widgets::text captcha;
23
+	cppcms::widgets::submit submit;
24
+	new_user_form(apps::wiki *w);
25
+	void generate_captcha();
26
+	bool virtual validate(); 
27
+};
28
+
29
+struct new_user : public master {
30
+	new_user_form form;
31
+	new_user(apps::wiki *w) : form(w){};
32
+};
33
+
34
+struct login : public master {
35
+	login_form form;
36
+	std::string new_user;
37
+	login(apps::wiki *w) : form(w){};
38
+};
39
+
40
+} // namespace content
41
+
42
+#endif

+ 58
- 0
src/wiki.cpp View File

@@ -0,0 +1,58 @@
1
+#include "wiki.h"
2
+#include <booster/regex.h>
3
+
4
+#include <cppcms/url_dispatcher.h>
5
+#include <cppcms/http_context.h>
6
+
7
+namespace apps {
8
+
9
+wiki::wiki(cppcms::service &srv) :
10
+	cppcms::application(srv),
11
+ 	conn(settings().get<std::string>("wikipp.connection_string")),
12
+	page(*this),
13
+	options(*this),
14
+	users(*this),
15
+	index(*this)
16
+{
17
+	add(page);
18
+	add(options);
19
+	add(users);
20
+	add(index);
21
+
22
+	script=settings().get<std::string>("wikipp.script");
23
+	cppcms::json::object langs = settings().at("wikipp.languages").object();
24
+	for(cppcms::json::object::const_iterator p=langs.begin();p!=langs.end();++p) {
25
+		lang_map[p->first]=p->second.str();
26
+	}
27
+}
28
+
29
+std::string wiki::root(std::string l)
30
+{
31
+	if(l.empty()) l=locale_name;
32
+	return script+"/"+l;
33
+}
34
+static const booster::regex lang_regex("^/(\\w+)(/.*)?$");
35
+
36
+void wiki::main(std::string url)
37
+{
38
+	booster::smatch res;
39
+	options.reset();
40
+	users.reset();
41
+	if(booster::regex_match(url,res,lang_regex)) {
42
+		std::map<std::string,std::string>::const_iterator p = lang_map.find(std::string(res[1]));
43
+		if(p==lang_map.end()) {
44
+			page.redirect();
45
+		}
46
+		else {
47
+			locale_name = p->first;
48
+			context().locale(p->second);
49
+			if(!dispatcher().dispatch(res[2]))
50
+				page.redirect(locale_name);
51
+		}
52
+	}
53
+	else
54
+		page.redirect();
55
+}
56
+
57
+
58
+} // apps

+ 48
- 0
src/wiki.h View File

@@ -0,0 +1,48 @@
1
+#ifndef WIKI_H
2
+#define WIKI_H
3
+#include <cppcms/application.h>
4
+#include <cppdb/frontend.h>
5
+
6
+#include "page.h"
7
+#include "users.h"
8
+#include "index.h"
9
+#include "options.h"
10
+
11
+
12
+
13
+namespace apps {
14
+
15
+class wiki : public cppcms::application {
16
+	friend class apps::page;
17
+	friend class apps::options;
18
+	friend class apps::users;
19
+	friend class apps::index;
20
+	friend class apps::master;
21
+
22
+	std::string script;
23
+public:
24
+	std::string conn;
25
+	// Data 
26
+	std::string locale_name;
27
+
28
+	// Applications 
29
+
30
+	apps::page page;
31
+	apps::options options;
32
+	apps::users users;
33
+	apps::index index;
34
+
35
+	std::string root(std::string locale_name="");
36
+	bool set_locale(std::string);
37
+	void run(std::string lang,std::string url);
38
+	//virtual void on_404();
39
+	virtual void main(std::string url);
40
+	wiki(cppcms::service &s);
41
+private:
42
+	std::map<std::string,std::string> lang_map;
43
+};
44
+
45
+}
46
+
47
+#endif
48
+

+ 47
- 0
templates/admin.tmpl View File

@@ -0,0 +1,47 @@
1
+<% skin view %>
2
+<% view login uses content::login extends master %>
3
+<% template title() %><% gt "WikiPP :: Login" %><% end %>
4
+<% template main() %>
5
+<form action="" method="post"><% csrf %>
6
+<table>
7
+<% form as_table form %>
8
+</table>
9
+</form>
10
+<% if not empty new_user %>
11
+	<p><strong><a href="<%= new_user %>"><% gt "Register as new user" %></a></strong></p>
12
+<% end %>
13
+<% end template %>
14
+<% end view %>
15
+<% view new_user uses content::new_user extends master %>
16
+<% template title() %><% gt "WikiPP :: Register" %><% end %>
17
+<% template main() %>
18
+<script type="text/javascript"><!--
19
+	document.write('<fo')
20
+	document.write('rm act')
21
+	document.write('ion="" m')
22
+	document.write('ethod="po')
23
+	document.write('st">')
24
+	-->
25
+</script>
26
+<% csrf %>
27
+<table>
28
+<% form as_table form %>
29
+</table>
30
+<script type="text/javascript"><!--
31
+	document.write('</fo')
32
+	document.write('rm>')
33
+	-->
34
+</script>
35
+<% end template %>
36
+<% end view %>
37
+<% view edit_options uses content::edit_options extends master %>
38
+<% template title() %><% gt "WikiPP :: Edit Options" %><% end %>
39
+<% template main() %>
40
+<form action="" method="post"><% csrf %>
41
+<table style="width:100%" >
42
+<% form as_table form %>
43
+</table>
44
+</form>
45
+<% end template %>
46
+<% end view %>
47
+<% end skin %>

+ 28
- 0
templates/hist.tmpl View File

@@ -0,0 +1,28 @@
1
+<% skin view %>
2
+<% view history uses content::history extends master %>
3
+<% template title() %><% gt "WikiPP :: History" %> :: <%= title %><% end %>
4
+<% template navigation() %>
5
+<a href="<%= page_link %>"><% gt "Back to page" %></a>
6
+&nbsp;/&nbsp;
7
+<% include master::navigation() %>
8
+<% end template %>
9
+<% template main() %>
10
+<% foreach row in hist %>
11
+	<ul>
12
+	<% item %>
13
+	<li>
14
+		<% gt "Version {1,num}, changed at {2,dt=s}, by {3}" using row.version, row.update, row.author %>,
15
+		<a href="<%= row.show_url %>"><% gt "Show" %></a>,
16
+		<a href="<%= row.edit_url %>"><% gt "Edit (rollback)" %></a><% if not empty row.diff_url %>, 
17
+			<a href="<%= row.diff_url %>"><% gt "Diff to previous" %></a>
18
+			<% end %>
19
+	</li>
20
+	<% end %>
21
+	</ul>
22
+<% empty %>
23
+<h2><% gt "History is empty" %></h2>
24
+<% end %>
25
+<% if not empty page %><p><a href="<%= page %>"><% gt "Next page" %></a></p><% end %>
26
+<% end template %>
27
+<% end view %>
28
+<% end skin %>

+ 114
- 0
templates/main.tmpl View File

@@ -0,0 +1,114 @@
1
+<% c++ #include "content.h" %>
2
+<% xhtml %>
3
+<% skin view %>
4
+<% view master uses content::master %>
5
+<% template title() %><% gt "Wellcome to WikiPP" %><% end %>
6
+<% template navigation() %>
7
+<a href="<%= login_link %>"><span id="loginout"></span></a>
8
+&nbsp;/&nbsp;
9
+<a href="<%= edit_options %>"><% gt" Users Area" %></a>
10
+<% end template %>
11
+<% template navbar() %>
12
+<%= about | ext markdown %>
13
+<hr/>
14
+<h2><% gt "Navigation" %></h2>
15
+<ul>
16
+	<li><a href="<%= toc %>"><% gt "Index" %></a></li>
17
+	<li><a href="<%= changes %>"><% gt "Changes" %></a></li>
18
+</ul>
19
+<% foreach l in languages %>
20
+<h2><% gt "Main Page" %></h2>
21
+<ul>
22
+<% item %><li><a href="<%= l.second %>"><%= l.first %></a></li><% end %>
23
+</ul>
24
+<% end %>
25
+<% end template %>
26
+<% template main() %><% end %>
27
+<% template wiki_title() %><%= wiki_title %><% end %>
28
+<% template sidebar() %><% end %>
29
+<% template render() %>
30
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
31
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
32
+<html xmlns="http://www.w3.org/1999/xhtml">
33
+<head>
34
+	<title><% include title() %></title>
35
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
36
+	<link href="<%= media %>/style.css" rel="stylesheet" type="text/css" />
37
+	<% if not empty syntax_highlighter %>
38
+		<script language="javascript"  src="<%= media %>/sh/Scripts/shCore.js"></script>
39
+		<script language="javascript"  src="<%= media %>/sh/Scripts/shBrushCpp.js"></script>
40
+		<link href="<%= media %>/sh/Styles/SyntaxHighlighter.css" rel="stylesheet" type="text/css" />
41
+	<% end %>
42
+	<link href="<%= media %>/style-<% if rtl %>rtl<% else %>ltr<%end%>.css" rel="stylesheet" type="text/css" />
43
+</head>
44
+<body onload="loginout()">
45
+	<script type="text/javascript">
46
+	<!--
47
+                function get_cookie(c_name)
48
+                {
49
+                	c_name='<%= cookie_prefix %>' + c_name; 
50
+                        if (document.cookie.length>0){
51
+                                c_start=document.cookie.indexOf(c_name + "=");
52
+                                if (c_start!=-1){ 
53
+                                        c_start=c_start + c_name.length+1; 
54
+                                        c_end=document.cookie.indexOf(";",c_start);
55
+                                        if (c_end==-1) c_end=document.cookie.length;
56
+                                                return decodeURIComponent(document.cookie.substring(c_start,c_end));
57
+                                } 
58
+                        }
59
+                        return "";
60
+                }
61
+		function loginout(){
62
+			var element=document.getElementById('loginout');
63
+			var username=get_cookie('username');
64
+			if(username=='')  {
65
+				element.innerHTML='<% gt "Login" %>';
66
+			}
67
+			else {
68
+				element.innerHTML='<% gt "Logout " %>('+username+')';
69
+			}
70
+		}
71
+		-->
72
+	</script>
73
+<div id="page" >
74
+	<div id="header">
75
+		<h1 id="title"><% include wiki_title() %></h1>
76
+	</div>
77
+	<div id="path">
78
+		<a href="<%= main_local %>"><% gt "Main" %></a>
79
+		&nbsp;/&nbsp;
80
+		<% include navigation()%>
81
+	</div>
82
+	<div id="maincontent">
83
+		<h1><% include title() %></h1>
84
+		<% include main() %>
85
+	</div>
86
+	<div id="sidecontent">
87
+		<% include navbar() %>
88
+		<% include sidebar() %>
89
+		<hr/>
90
+		<p><a href="http://jigsaw.w3.org/css-validator/check/referer"><% gt "Valid CSS" %></a> 
91
+		| <a href="http://validator.w3.org/check?uri=referer"><% gt "Valid XHTML 1.0" %></a>
92
+		</p>
93
+	</div>
94
+	<div id="footer">
95
+		<div id="copyrightdesign">
96
+		<%= copyright %> | <% gt "Template design based on <a href=\"http://ContentedDesigns.com\">Contented Designs</a>" %>
97
+		</div>
98
+		<div id="footercontact">
99
+		<a href="<%= contact %>"><% gt "Contact" %></a>
100
+		</div>
101
+	</div>
102
+</div>
103
+	<% if not empty syntax_highlighter %>
104
+	<script language="javascript" >
105
+	<!--
106
+	dp.SyntaxHighlighter.HighlightAll('code');
107
+	-->
108
+	</script>
109
+	<% end %>
110
+</body>
111
+</html>
112
+<% end template %>
113
+<% end view %>
114
+<% end skin %>

+ 122
- 0
templates/page.tmpl View File

@@ -0,0 +1,122 @@
1
+<% skin view %>
2
+<% view page uses content::page extends master %>
3
+<% template sidebar() %>
4
+	<% if not empty sidebar %>
5
+	<hr/>
6
+	<div id="navbar_links" >
7
+		<%= sidebar | ext markdown %>
8
+	</div>
9
+	<% end %>
10
+<% end %>
11
+<% template title() %><%= title %><% end %>
12
+<% template navigation() %>
13
+<% if not empty edit_link %>
14
+<a href="<%= edit_link %>"><% gt "Edit" %></a>
15
+&nbsp;/&nbsp;
16
+<a href="<%= history_link %>"><% gt "History" %></a>
17
+&nbsp;/&nbsp;
18
+<% end %>
19
+<% include master::navigation() %>
20
+<% end template %>
21
+<% template main() %>
22
+<%= content | ext markdown %>
23
+<% end %>
24
+<% end view %>
25
+<% view edit_page uses content::edit_page extends page %>
26
+<% template title() %><% if new_page %><% gt "New Article" %><% else %><% gt "Edit" %><% if not empty title %>:<%= title %><% end %><% end %><% end %>
27
+<% template navigation() %>
28
+<% if not empty edit_link %>
29
+<a href="<%= back %>"><% gt "Back to page" %></a>
30
+&nbsp;/&nbsp;
31
+<a href="<%= history_link %>"><% gt "History" %></a>
32
+&nbsp;/&nbsp;
33
+<% end %>
34
+<% include master::navigation() %>
35
+<% end template %>
36
+<% template main() %>
37
+<% if not empty title %>
38
+	<% include page::main() %>
39
+<% end %>
40
+	<script type="text/javascript">
41
+	<!--
42
+		document.write('<for')
43
+		document.write('m actio')
44
+		document.write('n="')
45
+		document.write('<%= submit %>" me')
46
+		document.write('thod="po')
47
+		document.write('st">')
48
+	-->
49
+	</script>
50
+	<% csrf %>
51
+	<table>
52
+	<% form as_table form.fields %>
53
+	</table>
54
+	<p><% form as_space form.buttons %></p>
55
+	<script type="text/javascript">
56
+	<!-- 
57
+		document.write('</fo')
58
+		document.write('rm>')
59
+	-->
60
+	</script>
61
+<% end template %>
62
+<% end view %>
63
+<% view page_hist uses content::page_hist extends page %>
64
+<% template title() %>
65
+<% include page::title() %> 
66
+<% end template %>
67
+<% template navigation() %>
68
+	<a href="<%= rollback %>"><% gt "Edit this version (rollback)" %></a>
69
+	&nbsp;/&nbsp;
70
+	<% include page::navigation() %>
71
+<% end template %>
72
+<% template main() %>
73
+<div class="published"><% gt "(version {1,num}, from {2,dt=s})" using version, date %></div>
74
+<% include page::main() %>
75
+<% end template %>
76
+<% end view %>
77
+<% view diff uses content::diff extends master %>
78
+<% template title() %><% gt "Difference \"{1}\" ver. {2} versus ver. {3}" using title,v1,v2 %><% end template %>
79
+<% template navigation() %>
80
+	<a href="<%= edit_v1 %>"><% gt "Edit version {1,num}" using v1 %></a>
81
+	&nbsp;/&nbsp;
82
+	<a href="<%= edit_v2 %>"><% gt "Edit version {1,num}" using v2 %></a>
83
+	&nbsp;/&nbsp;
84
+	<% include master::navigation() %>
85
+<% end template %>
86
+<% template show_diff(content::diff_t &content) %>
87
+<table style="width:100%" >
88
+	<% foreach r in content %>
89
+	<% item %>
90
+	<tr class="<% if (r.first<0) %>d_del<% elif (r.first>0) %>d_add<% else %>d_no<% end %>" >
91
+		<td><code><%= r.second %></code></td>
92
+	</tr>
93
+	<% end %>
94
+	<% end %>
95
+</table>
96
+<% end template %>
97
+<% template main() %>
98
+<% if no_versions %>
99
+	<h2><% gt "No such page or version exist" %></h2>
100
+<% elif no_diff %>
101
+	<h2><% gt "No difference between these versions" %></h2>
102
+<% else %>
103
+	<% if title_diff %>
104
+	<h2><% gt "Titles" %>:</h2>
105
+	<table style="width:100%">
106
+	<tr><th><% gt "Version {1}" using v1 %></th><th><% gt "Version {1}" using v2 %></th>
107
+	<tr><td><%= title_1 %></td><td><%= title_2 %></td></tr>
108
+	</table>
109
+	<% end %>
110
+	<% if content_diff %>
111
+		<h2><% gt "Content" %>:</h2>
112
+		<% include show_diff(content_diff_content) %>
113
+	<% end %>
114
+	<% if sidebar_diff %>
115
+		<h2><% gt "Sidebar" %>:</h2>
116
+		<% include show_diff(sidebar_diff_content) %>
117
+	<% end %>
118
+	</table>
119
+<% end %>
120
+<% end template %>
121
+<% end view %>
122
+<% end skin %>

+ 44
- 0
templates/toc.tmpl View File

@@ -0,0 +1,44 @@
1
+<% c++ #include "content.h" %>
2
+<% skin view %>
3
+<% view toc uses content::toc extends master %>
4
+<% template title() %><% gt "Index of Articles" %><% end %>
5
+<% template main() %>
6
+<% foreach row in table %>
7
+<table id="toc_table">
8
+	<% item %>
9
+	<tr>
10
+		<% foreach cell in row %>
11
+		<% item %>
12
+			<% if not empty cell.title %>
13
+				<td><a href="<%= cell.url %>"><%= cell.title %></a>
14
+			<% else %>
15
+				<td>&nbsp;</td>
16
+			<% end %>
17
+		<% end item %>
18
+		<% end %>
19
+	</tr>
20
+	<% end item %>
21
+</table>
22
+<% end foreach %>
23
+<% end template %>
24
+<% end view %>
25
+<% view recent_changes uses content::recent_changes extends master %>
26
+<% template title() %><% gt "Recent Changes" %><% end %>
27
+<% template main() %>
28
+<% foreach c in content %>
29
+	<ul>
30
+	<% item %>
31
+	<li><a href="<%= c.url %>"><%= c.title %></a> &mdash; 
32
+		<% gt "version {1,num}, at {2,dt=s}, by {3}" using c.version,c.created,c.author %><% if not empty c.diff_url %>, 
33
+			<a href="<%= c.diff_url %>"><% gt "Diff to previous" %></a><% end %>
34
+
35
+	</li>
36
+	<% end item %>
37
+	</ul>
38
+	<% if not empty next %><p><a href="<%= next %>"><% gt "Next Page" %></a></p><% end %>
39
+<% empty %>
40
+<h2><% gt "No more changes" %></h2>
41
+<% end %>
42
+<% end template %>
43
+<% end view %>
44
+<% end skin %>

+ 71
- 0
wikipp.log View File

@@ -0,0 +1,71 @@
1
+2012-02-01 13:43:32; cppcms_http, info: GET /wikipp (http_api.cpp:247)
2
+2012-02-01 13:43:32; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
3
+2012-02-01 13:43:32; cppcms_http, info: GET /wikipp/en/page/main/edit (http_api.cpp:247)
4
+2012-02-01 13:43:32; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
5
+2012-02-01 13:43:32; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
6
+2012-02-01 13:43:42; cppcms_http, info: POST /wikipp/en/page/main/edit (http_api.cpp:247)
7
+2012-02-01 13:43:42; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
8
+2012-02-01 13:43:42; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
9
+2012-02-01 13:43:42; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
10
+2012-02-01 13:43:44; cppcms_http, info: GET /wikipp/en/login/ (http_api.cpp:247)
11
+2012-02-01 13:43:44; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
12
+2012-02-01 13:43:44; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
13
+2012-02-01 13:43:46; cppcms_http, info: GET /wikipp/en/register/ (http_api.cpp:247)
14
+2012-02-01 13:43:46; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
15
+2012-02-01 13:43:46; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
16
+2012-02-01 13:43:53; cppcms_http, info: POST /wikipp/en/register/ (http_api.cpp:247)
17
+2012-02-01 13:43:54; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
18
+2012-02-01 13:43:54; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
19
+2012-02-01 13:43:54; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
20
+2012-02-01 13:43:56; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
21
+2012-02-01 13:43:56; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
22
+2012-02-01 13:43:56; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
23
+2012-02-01 13:43:57; cppcms_http, info: GET /wikipp/pl (http_api.cpp:247)
24
+2012-02-01 13:43:57; cppcms_http, info: GET /wikipp/pl/page/main (http_api.cpp:247)
25
+2012-02-01 13:43:57; cppcms_http, info: GET /wikipp/pl/page/main/edit (http_api.cpp:247)
26
+2012-02-01 13:43:57; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
27
+2012-02-01 13:43:57; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
28
+2012-02-01 13:43:58; cppcms_http, info: GET /wikipp/en (http_api.cpp:247)
29
+2012-02-01 13:43:58; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
30
+2012-02-01 13:43:58; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
31
+2012-02-01 13:43:58; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
32
+2012-02-01 13:43:59; cppcms_http, info: GET /wikipp/ru (http_api.cpp:247)
33
+2012-02-01 13:43:59; cppcms_http, info: GET /wikipp/ru/page/main (http_api.cpp:247)
34
+2012-02-01 13:43:59; cppcms_http, info: GET /wikipp/ru/page/main/edit (http_api.cpp:247)
35
+2012-02-01 13:44:00; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
36
+2012-02-01 13:44:00; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
37
+2012-02-01 13:44:00; cppcms_http, info: GET /wikipp/he (http_api.cpp:247)
38
+2012-02-01 13:44:00; cppcms_http, info: GET /wikipp/he/page/main (http_api.cpp:247)
39
+2012-02-01 13:44:00; cppcms_http, info: GET /wikipp/he/page/main/edit (http_api.cpp:247)
40
+2012-02-01 13:44:01; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
41
+2012-02-01 13:44:01; cppcms_http, info: GET /media/style-rtl.css (http_api.cpp:247)
42
+2012-02-01 13:44:04; cppcms_http, info: GET /wikipp/he/page/main (http_api.cpp:247)
43
+2012-02-01 13:44:04; cppcms_http, info: GET /wikipp/he/page/main/edit (http_api.cpp:247)
44
+2012-02-01 13:44:04; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
45
+2012-02-01 13:44:04; cppcms_http, info: GET /media/style-rtl.css (http_api.cpp:247)
46
+2012-02-01 13:44:05; cppcms_http, info: GET /wikipp/en (http_api.cpp:247)
47
+2012-02-01 13:44:05; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
48
+2012-02-01 13:44:05; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
49
+2012-02-01 13:44:05; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
50
+2012-02-01 13:44:06; cppcms_http, info: GET /wikipp/pl (http_api.cpp:247)
51
+2012-02-01 13:44:06; cppcms_http, info: GET /wikipp/pl/page/main (http_api.cpp:247)
52
+2012-02-01 13:44:06; cppcms_http, info: GET /wikipp/pl/page/main/edit (http_api.cpp:247)
53
+2012-02-01 13:44:06; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
54
+2012-02-01 13:44:06; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
55
+2012-02-01 13:44:11; cppcms_http, info: GET /wikipp/ru (http_api.cpp:247)
56
+2012-02-01 13:44:11; cppcms_http, info: GET /wikipp/ru/page/main (http_api.cpp:247)
57
+2012-02-01 13:44:11; cppcms_http, info: GET /wikipp/ru/page/main/edit (http_api.cpp:247)
58
+2012-02-01 13:44:11; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
59
+2012-02-01 13:44:11; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
60
+2012-02-01 13:44:13; cppcms_http, info: GET /wikipp/he (http_api.cpp:247)
61
+2012-02-01 13:44:13; cppcms_http, info: GET /wikipp/he/page/main (http_api.cpp:247)
62
+2012-02-01 13:44:13; cppcms_http, info: GET /wikipp/he/page/main/edit (http_api.cpp:247)
63
+2012-02-01 13:44:13; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
64
+2012-02-01 13:44:13; cppcms_http, info: GET /media/style-rtl.css (http_api.cpp:247)
65
+2012-02-01 13:44:15; cppcms_http, info: GET /wikipp/en (http_api.cpp:247)
66
+2012-02-01 13:44:15; cppcms_http, info: GET /wikipp/en/page/main (http_api.cpp:247)
67
+2012-02-01 13:44:15; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
68
+2012-02-01 13:44:15; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)
69
+2012-02-01 13:44:24; cppcms_http, info: GET /wikipp/en/changes/ (http_api.cpp:247)
70
+2012-02-01 13:44:24; cppcms_http, info: GET /media/style.css (http_api.cpp:247)
71
+2012-02-01 13:44:24; cppcms_http, info: GET /media/style-ltr.css (http_api.cpp:247)

Loading…
Cancel
Save