webcalendar

Check-in [8f1b474690]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Snapshot, latest Webcalendar into git
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | descendants | master | trunk
Files: files | file ages | folders
SHA3-256:8f1b474690a2841bf8847f71fa0a484eac9a1b1f14ac6c9bda24007bf125db6b
User & Date: ajv-899-334-8894@vsta.org 2017-05-29 22:43:11
Context
2017-05-29
22:44
Get ical export working. Add option to pull all user-selected layers. (Damn it's slow, but it works.) check-in: 490daaaec6 user: ajv-899-334-8894@vsta.org tags: master, trunk
22:43
Snapshot, latest Webcalendar into git check-in: 8f1b474690 user: ajv-899-334-8894@vsta.org tags: master, trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes

Added AUTHORS.

















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
Most of the code was written by:
  Craig Knudsen <cknudsenATcknudsen.com>


New features and bug fixes provided by:
  Jukka Aittola <Jukka.AittolaAThut.fi>
  Mike Baptiste <baptisteATcc-concepts.com>
  Ralph Bo&szlig;ler <rbosslerATgmx.de>
  Toby Cabot <tobyATtoby.cabotATpobox.com>
  Antonio Costa <accmdqATesoterica.pt>
  Lachlan Cox <lachieATzip.com.au>
  Matthew Crosby <mcrosbyATmarthon.org>
  Dominik Fischer <dfischerATmegla.de>
  Tollef Fog Heen <tollefATadd.no>
  T.R. Fullhart <kayosATkayos.org>
  Ken Harris <kharrisATlhinfo.com>
  Florian Helmberger <fhATenemy.org>
  Michiel Holtkamp <michielATreseau.nl>
  Jeff Hoover* <jhoovATthebusstop.net>
  Lucie Houel <lyly134ATcaramail.com>
  Peter Huetmannsberger <huetmannATsite38.ping.at>
  Thomas James <tbjamesATbellsouth.net>
  Ian R. Justman <ianjATcalweb.com>
  Thorsten Klein <kleinATlfm.rwth-aachen.de>
  Ulrich Leodolter <ulrichATlab1.psy.univie.ac.at>
  Benoit Maisonny <benoitATsynclude.com>
  Jonathan Mark <jhmarkATxenops.com>
  Ed Palmer <palmeredATusers.sourceforge.net>
  Otto Paukner <Otto.PauknerATm-v-l.de>
  Paul Reisdorf <preisdorfATbinus.net>
  Adam Roben* <adam.robenATgmail.com>
  David Rodrigues <drodrigATnetextensions.com>
  Adam Shantz* <adamATadamshantzDOTcom>
  Andy Skunza <askunzaATdynamix-ltd.com>
  Oliver Teuber <teuberATdevicen.de>
  Romuald Texier <romualdATidp9001.com>
  Frederic Tyndiuk <email address suppressed>
  Jan Willamowius <janATmobile.de>
  Vadim Zaliva <lordATcrocodile.org>
  Ray Jones* <rjonesATumces.edu>
  Bruce Bannon* <bbannonATusersDOTsourceforgeDOTnet>


* ( Development Team )


Translations:
 Bulgarian:
  Malen Malenov <malen_malenovATyahoo.com>
 Catalan:
  Tradu&iuml;t <infoATtraduit.com>
 Chinese-Big5:
  Liang-Kuan Liu <lianguanATpchome.com.tw>
 Croatian_utf8:
  Krunoslav Zubrinic <krunoslav.zubrinicATvip.hr>
 Czech:
  Hanu&scaron; Adler <hadATpenguin.cz>
 Danish:
  Allan Thraen <allanAT12go.dk>
  J&oslash;rgen Thomsen <jthATjth.net>
  Jens Th <photoATjens-th.com>
  Nicolaj Rasmussen <drlandauATmsn.com>
  Morten Nielsen <mniATit.dk>
  Leo Todaro <leotodaroAThotmail.com>
 Dutch:
  Marcel van der Boom <marcelAThsdev.com>
  Patrick Gutlich <pgutlichATcasema.net>
  Klaus Spithost <k.spithostATit-works.nl>
  Marieke Timmer <marieke.timmerATtijdhof.nl>
  Arnout Engelen <arnoutenATbzzt.net>
  Oliver Heesakkers <devATheesakkers.info>
 Estonian:
  Madis Listak <madisATnetbell.ee>
 Finnish:
  Juha-Matti &Aring;berg <juffeATliveware.fi>
  Jussi Siponen <jussi.siponenATposiona.com>
 French:
  Luc Capronnier <email address suppressed>
  Olivier Piquerez <PiquerezATtopd.ch>
  Yves Moenner <yves.moennerATmailcity.com>
  Romuald Texier <romualdtATfree.fr>
  Wilfrid Hubert
  G&eacute;rard Delafond
  Mario Dragone <mario.dragoneATreims.iufm.fr>
  erational <http://www.erational.org>
  Ivan Machetto
  Emmanuel Rihn <acontrecourantATonline_fr>
 Galician:
  Ra&uacute;l Araya Tauler <nubeiroATnubeiro.com>
 German:
  Markus Egartner <markus.egartnerATkh.hallein.at>
  Ralph Bo&szlig;ler <rbosslerATgmx.de>
  Peter Huetmannsberger <huetmannATsite38.ping.at>
 Greek:
  Paul Gessos <cham_gssAThotmail.com>
 Hebrew:
  Dov Zamir <dovATzamirfamily.com>
 Holo-Big5:
  Henry H. Tan-Tenn <share2002novATlomaji.com>
 Hungarian:
  Gyorgy Baffia <gyorgyATbaffia.hu>
  Laszlo Csecsy <boobaaATajrg.hu_>
  Istvan Bubreg <bubregATfreemail.hu>
 Icelandic:
  Kristofer Arnar Einarsson <kristoferATkristofer.com>
 Italian:
  Simone Cortesi <simoneATcortesi.com>
  Alessandro <a.orlandiATiol.it>
 Japanese:
  Makoto Hamanaka <VYA04230ATnifty.com>
  Tadashi Jokagi <elf2000ATusers.sourceforge.net>
 Korean:
  Joonyup Jeon <goodwillATwowbook.com>
 Norwegian:
  P&aring;l L&oslash;berg/Magni Ons&oslash;ien <initioATinitio.no>
  Hans Fredrik Nordhaug <hansfnATusers.sourceforge.net>
 Polish:
  Lipowczan Pawel <lpao2ATo2.pl>
  Jano <j4n0ATusers.sourceforge.net>
 Portuguese:
  Antonio Costa <accmdqATmail.esoterica.pt>
  Nuno Lopes <nuno.lopesATmaxitel.com>
 Portuguese/Brazil:
  S&eacute;rgio Oliveira <slolivATterra.com.br>
  Mauricio Piza <mpizaATformare.com.br>
  Paulino Michelazzo <paulinoATmichelazzo.com.br>
  Jos&eacute; Roberto Kerne <joserobertoATdicaslinux.com.br>
  Nuno Lopes <nmlATmaxitel.pt>
  Andre Oliveira <zack22ATig.com.br>
 Romanian:
  Dan Protopopescu <protopopATphysics.gla.ac.uk>
 Russian:
  Andre E. Bar&rsquo;yudin <baryudinATpob.huji.ac.il>
  Ilya G. Teterev <remirranATgmail.com>
 Spanish:
  Pedro Del Medico <pdmpATinterhoster.com>
  P&eacute;rez Rilo
  Eduardo Dominguez <lalo_notthispleaseATteligens.com>
  Mario Benito <mbenitoATmaberi.com>
 Swedish:
  Jesper Th&ouml;rn <jesperATthorn.as>
  Bernt Sj&ouml;str&ouml;m <berntATsjostrom.pchemma.nu>
 Turkish:
  Atilla Kazanci <supportATdig-it-berlin.de>
 Welsh:
  Wyn James <wynjamesATonetel.net.uk>


There are probably many others that I have inadvertantly missed.


Thank you all for contributing to WebCalendar!

Added GPL.html.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>GNU General Public License - GNU Project - Free Software Foundation (FSF)</title>
<link rev="made" href="mailto:webmasters@www.gnu.org">
<base href="http://www.gnu.org/licenses/gpl.html">
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#1F00FF" alink="#FF0000" vlink="#9900DD">
<h1>GNU General Public License</h1>
<a href="/graphics/philosophicalgnu.html"><img src="/graphics/philosophical-gnu-sm.jpg"
   alt=" [image of a Philosophical GNU] "
   width="160" height="200"></a>

<!-- Please keep this list alphabetical -->
<!-- tower, gpl.ja.html is Japanese translation of THIS PAGE, -->
<!-- NOT translation of GPL itself (gpl.ja.html contains the original -->
<!-- English version). So please do not remove the following. -->
<!-- Thanks -mhatta -->
<!-- The same for the Czech page. The entire text of GPL is not -->
<!-- translated on this page. Thanks Sisao -->

[
  <a href="/licenses/gpl.cs.html">Czech</a>
| <a href="/licenses/gpl.html">English</a>
| <a href="/licenses/gpl.ja.html">Japanese</a>
]

<!-- It is best to not enumerate the translations here in a menu bar, -->
<!-- It is best to have the users follow this link, so they have the FSF' -->
<!-- explanation about translations being unofficial, etc. -->

<p>
<ul>
  <li><a href="/licenses/gpl-violation.html"><em>What to do if you see a
       possible GPL violation</em></a>
  <li><a href="/licenses/translations.html"><em>Translations
       of the GPL</em></a>
  <li><a href="/licenses/gpl-faq.html"><em>GPL Frequently Asked Questions</em></a>
  <li>The GNU General Public License (GPL)
       <a href="/licenses/gpl.txt">in plain text format</a>
  <li>The GNU General Public License (GPL)
       <a href="/licenses/gpl.texi">in Texinfo format</a>
</ul>
<p>
<hr>

<p>

<h2>Table of Contents</h2>
<ul>

  <li><a name="TOC1" href="gpl.html#SEC1">GNU GENERAL PUBLIC LICENSE</a>
<ul>
<li><a name="TOC2" href="gpl.html#SEC2">Preamble</a>
<li><a name="TOC3" href="gpl.html#SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a>
<li><a name="TOC4" href="gpl.html#SEC4">How to Apply These Terms to Your New Programs</a>

</ul>
</ul>

<p>

<hr>

<p>

<h2><a name="SEC1" href="gpl.html#TOC1">GNU GENERAL PUBLIC LICENSE</a></h2>
<p>
Version 2, June 1991

</p>

<pre>
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
</pre>

<h2><a name="SEC2" href="gpl.html#TOC2">Preamble</a></h2>

<p>
  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

</p>
<p>
  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

</p>
<p>
  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

</p>
<p>
  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

</p>
<p>
  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

</p>
<p>
  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

</p>
<p>
  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

</p>
<p>
  The precise terms and conditions for copying, distribution and
modification follow.

</p>

<h2><a name="SEC3" href="gpl.html#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a></h2>

<p>

<strong>0.</strong>
 This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".
<p>

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

<p>

<strong>1.</strong>
 You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
<p>

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
<p>

<strong>2.</strong>
 You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
<p>

<ul>

<li><strong>a)</strong>
     You must cause the modified files to carry prominent notices
     stating that you changed the files and the date of any change.

<p>
<li><strong>b)</strong>
     You must cause any work that you distribute or publish, that in
     whole or in part contains or is derived from the Program or any
     part thereof, to be licensed as a whole at no charge to all third
     parties under the terms of this License.

<p>
<li><strong>c)</strong>
     If the modified program normally reads commands interactively
     when run, you must cause it, when started running for such
     interactive use in the most ordinary way, to print or display an
     announcement including an appropriate copyright notice and a
     notice that there is no warranty (or else, saying that you provide
     a warranty) and that users may redistribute the program under
     these conditions, and telling the user how to view a copy of this
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
</ul>

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
<p>

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
<p>

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

<p>

<strong>3.</strong>
 You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

<!-- we use this doubled UL to get the sub-sections indented, -->
<!-- while making the bullets as unobvious as possible. -->
<ul>

<li><strong>a)</strong>
     Accompany it with the complete corresponding machine-readable
     source code, which must be distributed under the terms of Sections
     1 and 2 above on a medium customarily used for software interchange; or,

<p>
<li><strong>b)</strong>
     Accompany it with a written offer, valid for at least three
     years, to give any third party, for a charge no more than your
     cost of physically performing source distribution, a complete
     machine-readable copy of the corresponding source code, to be
     distributed under the terms of Sections 1 and 2 above on a medium
     customarily used for software interchange; or,

<p>
<li><strong>c)</strong>
     Accompany it with the information you received as to the offer
     to distribute corresponding source code.  (This alternative is
     allowed only for noncommercial distribution and only if you
     received the program in object code or executable form with such
     an offer, in accord with Subsection b above.)
</ul>

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
<p>

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
<p>

<strong>4.</strong>
 You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

<p>

<strong>5.</strong>
 You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

<p>

<strong>6.</strong>
 Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

<p>

<strong>7.</strong>
 If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
<p>

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
<p>

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
<p>

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

<p>

<strong>8.</strong>
 If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

<p>

<strong>9.</strong>
 The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
<p>

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

<p>

<strong>10.</strong>
 If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

<p><strong>NO WARRANTY</strong></p>

<p>

<strong>11.</strong>
 BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

<p>

<strong>12.</strong>
 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

<p>

<h2>END OF TERMS AND CONDITIONS</h2>

<h2><a name="SEC4" href="gpl.html#TOC4">How to Apply These Terms to Your New Programs</a></h2>

<p>
  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

</p>
<p>
  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

</p>

<pre>
<var>one line to give the program's name and an idea of what it does.</var>
Copyright (C) <var>yyyy</var>  <var>name of author</var>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
</pre>

<p>
Also add information on how to contact you by electronic and paper mail.

</p>
<p>
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

</p>

<pre>
Gnomovision version 69, Copyright (C) <var>year</var> <var>name of author</var>
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'.  This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
</pre>

<p>
The hypothetical commands <samp>`show w'</samp> and <samp>`show c'</samp> should show
the appropriate parts of the General Public License.  Of course, the
commands you use may be called something other than <samp>`show w'</samp> and
<samp>`show c'</samp>; they could even be mouse-clicks or menu items--whatever
suits your program.

</p>
<p>
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

</p>

<pre>
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.

<var>signature of Ty Coon</var>, 1 April 1989
Ty Coon, President of Vice
</pre>

<p>
This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.

<hr>

Return to <a href="/home.html">GNU's home page</a>.
<p>
FSF &amp; GNU inquiries &amp; questions to
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
Other <a href="/home.html#ContactInfo">ways to contact</a> the FSF.
<p>
Comments on these web pages to
<a href="mailto:webmasters@www.gnu.org"><em>webmasters@www.gnu.org</em></a>,
send other questions to
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
<p>
Copyright notice above.<br />
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111,  USA
<p>
Updated:
<!-- hhmts start -->
Last modified: Sun Jul 15 13:13:30 CEST 2001
<!-- hhmts end -->
<hr>
</body>
</html>

Added NEWS.



































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
WebCalendar NEWS File
Version: $Id: NEWS,v 1.468.2.28 2013/02/22 15:56:46 cknudsen Exp $

This file lists significant changes to WebCalendar.  For a more detailed
list (that includes specific bugs fixed, please look at ChangeLog):

http://webcalendar.cvs.sourceforge.net/*checkout*/webcalendar/webcalendar/ChangeLog?&pathrev=REL_1_2

---------------------------------------------------------------------------

Version 1.2.7 (22 Jan 2013)
 - Security fix: Do not show the reason for a failed login (i.e. "no such user")
 - Security fix: Escape HTML characters in category name.
 - Security fix: Check all passed in fields (either via HTML form or via
   URL parameter) for certain malicious tags (script, embed, etc.) and
   generate fatal error if found.

Version 1.2.6 (07 Jan 2013)
 - Fix for "undefined function require_valide" bug
 - Other minor bug fixes.
 - Updated Greek translation

Version 1.2.5 (29 Feb 2012)
 - Fixes for various security vulnerabilities include LFI (local file
   inclusion), XSS (cross site scripting) and others.
 - Updated translations: German, German-utf8, Dutch, Dutch-utf8
 - Misc. minor bug fixes

Version 1.2.4 (08 Aug 2011)
 - Fixed XSS vulnerability: malicious javascript in event descriptions submitted
   by public can do bad things (create admin account, delete events, etc.)
   when the pending event is viewed by the admin.
 - Fixed bug: PHP warnings on search
 - Removed PHP warnings
 - Bug fix: undefined function date_default_timezone_set in older versions
   of PHP.

Version 1.2.3 (14 Aug 2010)
 - Fixed bug: could not save events with more than one category
 - Include backtrace in fatal errors when in development mode

Version 1.2.2 (14 Aug 2010)
 - Fixes for PHP warnings about default timezone not being set.

Version 1.2.1 (09 Apr 2010)
 - Addressed some published security vulnerabilities related to
   cross site scripting (XSS).
 - Fixed "500 Server Error" seen with PHP 5.2.8 and later.  Some users saw
   either blank web page or seg fault errors with this.
 - Fixed mb_language error message some non-English users were seeing in 1.2.0.
 - A handful of minor bugfixes and patches.
 - Updated translations: Italian

Version 1.2.0 (27 Sep 2008)
 - Added new 'Security Audit' page.
 - Moved hard-coded upcoming.php config setting to System Settings.
 - Added new RSS feed for Activity Log.  This will allow you to be
   notified via RSS of event approvals/rejections, email notification,
   new event submissions, event updates, etc.
 - Removed old hack for register_globals work-around that is no longer
   needed.  This will improve security.
 - Category icons can now be displayed next to events in upcoming.php
 - Updated Portuguese_BR translations

Version 1.2.b1 (25 Feb 2008)
 - Changed default installation user/password to root/none
 - Added read/write test to db_cache /tmp folder
 - The following translations were updated:
   French, German-UTF

Version 1.1.6 (19 Sep 2007)

 - This release fixes bugs found in 1.1.5.
   (For a complete list of changes, see the ChangeLog in CVS.)
 - Security:
   Fixes cross-site scripting (XSS) vulnerability in export_handler.php.

Version 1.1.5 (12 Sep 2007)

  - Security fix: vulnerability in $includeDir in functions.php
  - The following translations were updated:
    Indonesian

Version 1.1.4 (28 Aug 2007)

  - This release fixes bugs found in 1.1.3.

Version 1.1.3 (04 Aug 2007)

  - New Features / Enhancements:
    = Import / Export / iCalendar / hCalendar / RSS
      + VTIMEZONE information is now captured from imported ics files and can be reused
        for future exports. This greatly simplifies the process and speeds up exports.
    = User Interface
      + Added option to display end times in calendars
      + Added CAPTCHA validation option  to Public Access event creation
  - The following translations were updated:
    German
    Basque

Version 1.1.2 (18 Dec 2006)

  - New Features / Enhancements:
    = Site Extras
      + Radio control are now available 
      + Checkbox controls are now available. 
      + Multi-Select Select controls are now available. 
      + Site-Extra fields are now included in emails. 
      + You can now set where each Site Extra fields show up. 
        - All 
        - Email 
        - View (view_entry) 
        - Reports 
        - Reminders 
        Any combination of the above is possible using bitwise operators.
    = User Interface
      + Date Range Searches have been added
      + Site Extra Seaches have been added
      + Category Filter has beed added to Advanced Search
      + Added Category Color option
      + Admin can now specify a background image for inclusion into CSS
      + Added new feature 'Display Long Day Names'
      + Added new Color Picker with many options
      + Added new About WebCalendar page
      + Reports can now contain 'fullname'
      + When creating Reports, you can now simply click desired value
        and it will auto-insert at the cursor.
      + The top menu is now fully configurable and custom menus can be
        added easily. See includes/menu/menu_config.php for details.
      + Added 'System Log' in menu.  Added logging for adding/editing/deleting
        users and invalid logins.
      + Reorganized and grouped System Settings and user preferences

  - The following translations were updated:
    French-UTF8(new), German, Russian

---------------------------------------------------------------------------

Version 1.1.1 (15 Sep 2006)

  - Fixes:
    + Fixed vulnerablity: SQL injection possible in edit_template.php,
      activity_log.php, admin_handler.php, pref_handler.php, export_handler.php
    + Fixed security: exploit allows execution of code downloaded from
      remote server
    + HUGE list of fixes (see ChangeLog for details)

  - New Features / Enhancements / Changes:
    = Permissions
      + User Access Control: fine grain setting of all user's permissions
    = Import / Export / iCalendar / hCalendar / RSS
      + Read/write remote ical subscriptions with new icalclient.php file.
        Can be enabled in user preferences in the Subscripe/Publish area.
      + Added Remote Calendars which allow a WebCalendar user to view
        external iCalendar/ics (icalshare.com, etc.) or hCalendar files
        from within WebCalendar.
      + Improved iCal parsing
      + Export only a specified category
      + Implemented VTODO support with floating display of due date per RFC2445 
      + Allow users to import from Outlook 2003/XP CSV file
      + Palm Desktop datebook import works for versions 4.1.1 and newer
      + Added iCal FreeBusy support
      + Added RSS feed if admin and user preference are enabled for it.
    = Performance
      + Style sheets no longer included in each page (faster downloads)
      + Added caching of db requests and parsed translations.
    = Event Details
      + Full timezone support rather than timezone offset
      + Improved reminder UI and added repeating functionality per RFC2445
      + Can attach comments and documents to events using database BLOBs
      + Added support for events overlapping into next day
      + Added new Repeat type 'Manual' that allows adding Inclusions/Exclusions 
        without other repeat attributes.
      + Implemented a new repeating event system that incorporates most
        requirements of RFC2445.
        Multiple Categories, multiple Alarms and RDATE are now supported,
        along with the abiity to export VTIMEZONE elements if desired.
    = Event Approval
      + Approve/confirm/reject all unapproved events
      + Can add a comment for reject/accept event
    = User Interface
      + Added install wizard functionality that will create or update
        database tables.
      + New JS/DHTML top menu bar added
      + Use drop-down selection lists for selecting time
      + Divided content of preferences pages into tabs
      + Uploadable category icons
      + Modified upcoming.php to display tasks (see upcoming.php for details)
      + Layers can be global
      + Allow date styles to be specified in translation file
      + Use FCKEditor for editing HTML event descriptions
      + Added new time range options for reports: next 14/30/60/90/180/365 days
        This allows reports to show events starting with current date
      + Added ability to use custom header/stylesheet/trailer on a per-user
        basis via user preferences.
      + Optional lunar phases to month view
      + Allow site extras in reports
      + Added minical.php for using in iframe in external site
      + Added support for multiple public calendars by enabling
        nonuser calendars to act as public calendar.
      + Added ability to change text Public Access in system settings.
      + Added new view that will display similar to day.php and week.php do now
        except for multiple users (each in their own column)
    = User Authentication
      + User authentication by IMAP
      + User authentication from Joomla file (user-app-joomla.php)
      + Added user self-registration.
        blacklist and email notification are optional
    = Email
      + Added support for SMTP mail using PHPMailer
      + Email ics attachment to external event participants
      + Added sending of HTML mail (for reminders only now)
    = Database
      + Added support for IBM DB2
    = PHP
      + Do not require magic_quote PHP setting

  - The following translations were updated:
    + Czech, Danish, French, German, Greek (new), Hungarian, Norwegian, Polish,
      Portuguese_BR, Japanese (switched to UTF-8), Japanese-sjis (new),
      Japanese-eucjp, Portuguese

---------------------------------------------------------------------------

Version 1.0.0 (17 May 2005) aka Buster
  - Fixed the following bug reports on SourceForge:
      1202127: [ 1187734 ] Timezone offset problems still exist
      1201821: Bypass user_sees_only_his_groups
      1193835: Creator cannot edit a nonuser-event after Admin changes it.
      1193579: Untimed shows up wrong in edit page
      1189515: Possible to create blank usernames
      1190687: users.php called as public
      1190699: export.php available to public
      1190704: public can access assistant_edit.php
      1103215: Invalid work hours
      1187734: Timezone offset problem
      1120897: Conflict with exceptions
      1181682: Report with no name entered -> phantom report!
      1179423: private events displayed on reports
      1183714: Translation error
      1154432: vCal import from Mozilla fails to translate quoted-printable
      1176164: iCalendar import fatally corrupts database
      1181682: Reports with just spaces for a name cannot be edited
      1179403: Availability selection fails when Time Format =24
      1065461: timezone offset & all-day events
      1107253: time zone offset
      1140453: Time zone offset in email notifications
      1148602: External Recipients with same name fails
      1160167: 12AM Events cause display problems in edit_entry.php
      1158769: Category lost when modifing event by Admin
      1168686: Month display collides with minicals on Safari
      1168682: RC3 Language Detection Broken for Safari.
      1169403: Public Access not DEFAULT selected if Particiapants not shown. 
      1169078: Bad function call in import_handler.php
      1168092: Overlapping events display problem
      1167281: View_l loses colour for today
      1167790: class=selectedday assignments in other than day.php
      1162486: Path exposure issue with view_entry.php

  - Other bugs fixed:
    + Fixed problem with ical import weekly BYDAY parsing in import_ical.php
    + Fixed problem with missing $cat_id in week and day URLs in month.php
    + Fixed problem with second edit of a single event in a repeating series 
      losing linkage with the original event.
    + Fixed problem with views_edit.php, select groups not returning menbers
    + Fixed problem with 12AM event not adding hour=0 to URL in week.php
    + Fixed day.php rendering problem in Safar
    + Applied bug fix 1151442: Overlapping events display error in week.php

  - New Features / Enhancements / Changes:
    + Split import/export back to two separate links & pages
    + Moved contents of scheduling tab to details tab
    + Updated install/index.php to improve security and display advanced php info
    + Added new DEFAULT webcal_config values to all sql table definition files
    + Removed most instances of htmlentities as unneeded
    + Admin no longer needs to approve Public events that they create
    + Added option to set LDAP_OPT_PROTOCOL_VERSION in user-ldap.php
    + Updated install web page to work better on Windows systems.
      Added display of current PHP settings.
    + When viewing a report, if allow_html_description is enabled but no HTML
      is found in an event description, use nl2br to preserve plain text
      formatting.

  - The following translations were updated:
    + Danish, Finnish, German, French, Japanese, Norwegian, Polish

---------------------------------------------------------------------------

Version 1.0RC3 (11 Mar 2005)
  - Fixed the following bug reports on SourceForge:
      1156729: Global-view with no valid user creates a non-translatable message
      1152863: Japanese strings munged by reports.php and upcoming.php
      1124461: Apostrophe in Text Aborts Translation
      1154854: Nonuser cals not showing up in views
      1154007: Highlight today in Year view
      1088772: Nonuser calendar w/ Public as DEFAULT participant
      1145390: Merge arrays with array_merge vs + in view_t.php
      1151442: Overlapping events display error in day.php
      1146037: Availibility legend size not dynamic and not centered in IE.
      1148603: Assistants can't view Bosses Unapproved Events.
      1145342: Category selection not tranferred to edit_entry page.
      1118121: get_admins in user-ldap has bad search
      1123508: RC3 browser language detection always returns none.
      1112787: missing charset in upcoming.php
  - Other bugs fixed:
    + Fixed problem with upcoming.php header. xml:lang and lang were set to full 
      LANGUAGE value, not abbreviation.
    + Fixed problem with upcoming.php with You are not Authorized error message
      being sent without a header. 
    + Fixed problem with popups.php with long text strings going off screen.
      Maximum width is now configurable.
    + Fixed issue with Application Name containing ? characters in logon.php.
      If Application Name = Title then translate, else use Admin defined 
      name and run through htmlspecialchars
    + Fixed issues with display_small_month URLs. Extra & if no $user specified.
    - Add meta tag for charset since MSIE requires it.
    + Fixed broken advanced search that would not allowing searching other
      users' calendars.  Also added searching non-user calendars.
    + Added javascript that enables visibility of the start/end time or
      duration on the edit_entry page from availability.php
    + Fixed printer friendly view problem. With refresh on, the refresh URL
      reverted to the regular page
    + Fixed date_selection_html function to include values for day control
    + Purge events was not deleting from webcal_entry_ext_user table
    + Fixed issues with ODBC returning 'invalid db_type'
    + Fixed issue where month.php and mini-calendar today highlight
      based on server time
  - New Features / Enhancements / Changes:
    + Merged task files into entry files
    + Added 'Public Access' to Manage Calendar of: list, if Admin. 
    + Allow user-created views to be the DEFAULT view set in user preferences.
      After saving or deleting an event, the user will return to this page.
    + Replaced popups.php code with new knoppix based code. This should eliminate
      the problems with popups going off screen. Popups also follow the cursor now,
      but can be disabled in the file.
    + Replaced all instances of forms[0] in javascript with the real form
      names. This will allow WebCalendar to co-exist with other forms on
      the same page.
    + Added patch to allow TLS with LDAP
    + Added patch 900968: Add outlook-style availability popup
    + Added global views (available to all users)
    + Added option to select all users for a view (rather than having
      to select all users in the list).  If users are added later, they
      will be automatically included in the view.
    + Converted comments for use with phpDocumentor
  - The following translations were updated:
    + Dutch, Japanese (utf8, euc-jp, shift-jis), Spanish, German

---------------------------------------------------------------------------

Version 1.0RC2 (09 Feb 2005)
  - Fixed the following bugs reports on SourceForge:
      1116008: Got invalid user error when clicking on '+' icon
               to add new event
  - Other bugs fixed:
    + Fixed a problem with the Repeat Tab on edit_entry page, if disabled, 
      the SAVE button was hidden as well.
  - New Features / Enhancements / Changes:
    + Modified the way settings.php file is read to handle unix/dos/mac
      format and also check main directory and include directory.
    + In day and week view, time slots with events will now use a different
      background color than time slots that are empty.  (This restores
      how this worked a couple of versions ago.)
    + Many code changes were made to prevent the undefined variable
      warning that users may get if they have the PHP error_reporting
      setting enabled.
    + Documentation updated to System Administrator Guide including
      new instructions for setting up reminders on Windows.
  - The following translations were updated:
    + Czech

---------------------------------------------------------------------------

Version 1.0RC1 (04 Feb 2005)
  - Fixed the following bugs reports on SourceForge:
       824268: Emails notifications used wront timezone
       931096: Restrict views and view edits to owner of that view
       986774: Editing category as assistant was not working
      1061746: layout issues with views (daily)
      1066440: End Time increased by timezone offset
      1085337: Categories combo-box in month.php in assistant mode
      1088857: SQL bug affecting ODBC users when viewing event
      1101823: Problem importing palm desktop datebook.dat file
      1102167: custom header when non-admin user
      1109141: Email notifications where using sender language
               rather than recipient language
      1109323: Error in LDAP function for getting list of admins
      1087604: Vanishing Layers / cookies
      1086357: repeating details display
      1085846: SQL error in when listing users on some databases
      1085971: repeat tab does not display details
      1074403: Day View is not accounting for server offset
  - Other bugs fixed:
    + Security fix: Fixed protential problem if a user attempts to login
      with a username that has charaters that will affect the database.
    + When using web-based authentication, two database connections
      were being opened and only one was being closed.
    + vCal import was completely broken
    + Fixed problem using htmlarea where event description would not be saved
    + View Event page would not display links to edit/delete under
      some circumstances
    + Fixes for WN web server
    + Removed duplicate trailer from edit user page (when using a custom
      trailer)
  - New Features / Enhancements:
    + MS SQL Server is now suppported
    + If php.ini setting for file_uploads is not enabled, then indicate
      this on the import page
    + Streamlined layers.php & made layers only be displayed when layers
      are enabled
    + Updated Admin docs for content & xhtml/css validity
    + Added new documentation in docs directory:
      WebCalendar-Functions.html
      WebCalendar-DeveloperGuide.html
      WebCalendar-Styling.html
    + Fixed various xhtml/css issues
    + Updated reading of settings file to better handle when file
      is not in exact format we are expecting.
    + Added database sanity check
    + Updated DEFAULT color scheme (Will only apply to new installs)
    + When html is allowed in event description, still replace newline with
      html break in view page and event popup if the user did not use any html.
    + Fixing users.php so it only shows a single user's info when the user
      isn't an admin
    + Added ability to authenticate users with postnuke user info.
    + Added support for automatic gradient background images for table cells
  - The following translations were updated:
    + Japanese (with support for 3 character sets)
    + Romanian (new)
    + French
    + German
    + Italian
    + Norwegian

Added README.html.







































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "DTD/xhtml1-transitional.dtd">
<!-- $Id: README.html,v 1.29.2.2 2007/08/06 02:28:29 cknudsen Exp $ -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
  <title>WebCalendar README</title>
  <style type="text/css">
<!--
  body {
    background-color: #FFFFFF;
    font-family: arial, verdana;
  }
  a {
    text-decoration: none;
  }
  table {
    border-width: 0;
  }
  dt {
    font-weight: bold;
  }
  tr {
    background-color: #606080;
  }
  td {
    background-color: #E0E0E0;
    vertical-align: top;
  }
  h3 {
    background-color: #191970;
    color: #FFFFFF;
    padding: 5px;
  }
-->
  </style>
  </head>
  <body>
    <h2>WebCalendar README</h2>
    <table cellpadding="10">
      <tr>
        <td style="font-weight:bold;">URL:</td>
        <td><a href="http://www.k5n.us/webcalendar.php">www.k5n.us/webcalendar.php</a></td>
      </tr>
      <tr>
        <td style="vertical-align:top; font-weight:bold;">Developers:</td>
        <td valign="top">
          Craig Knudsen,
          <a href="mailto:&#99;&#114;&#97;&#105;&#103;&#64;&#107;&#53;&#110;&#46;&#117;&#115;">&#99;&#114;&#97;&#105;&#103;&#64;&#107;&#53;&#110;&#46;&#117;&#115;</a>
          <a href="http://www.k5n.us/">http://www.k5n.us</a><br />
          Jeff Hoover<br />
          Adam Shantz,
          <a href="mailto:adamATadamshantzDOTcom">adamATadamshantzDOTcom</a>,
          <a href="http://adamshantz.com">adamshantz.com</a><br />
          Ray Jones, <a href="mailto:rjonesATumcesDOTedu">rjonesATumcesDOTedu</a><br />
          Adam Roben,
          Bruce Bannon
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Documentation:</td>
        <td>
          <a href="docs/WebCalendar-SysAdmin.html">System Administrator's Guide</a>
          (Installation instructions, FAQ)<br />
          <a href="docs/WebCalendar-UserManual.html">User Manual</a><br />
          <a href="UPGRADING.html">Upgrading Instructions</a>
          (<strong>Required</strong> when upgrading from an older version)<br />
          <a href="GPL.html">License</a><br />
          <a href="ChangeLog">History of Changes</a><br />
          <a href="http://webcalendar.sourceforge.net/demo/">Online Demo</a>
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Developer Resources:</td>
        <td>
          <a href="http://sourceforge.net/projects/webcalendar/">Sourceforge.net Home</a><br />
          <a href="docs/WebCalendar-Functions.html">WebCalendar-Functions.html</a><br />
          <a href="docs/WebCalendar-Database.html">WebCalendar-Database.html</a><br />
          <a href="docs/WebCalendar-DeveloperGuide.html">WebCalendar-DeveloperGuide.html</a><br />
          <a href="http://sourceforge.net/forum/forum.php?forum_id=11588">Help/Troubleshooting Forum</a><br />
          <a href="http://sourceforge.net/forum/forum.php?forum_id=11587">Open Discussion Forum</a><br />
          <a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=103870">Bug Reports</a><br />
          <a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=303870">Patches</a><br />
          <a href="https://sourceforge.net/project/showfiles.php?group_id=3870">Latest Version</a>
        </td>
      </tr>
    </table>
    <h3>Note</h3>
    <p>For a complete feature list, system requirements, and installation instructions, please see the <a href="docs/WebCalendar-SysAdmin.html">WebCalendar System Administrator's Guide</a>.</p>
    <h3>Outstanding issues</h3>
    <ul>
      <li>Updated translations (some are slightly out of date)</li>
    </ul>
    <h3>Possible features for future releases</h3>
    <ul>
      <li>See <a href="http://www.k5n.us/webcalendar.php?topic=Plans">Plans</a> on the WebCalendar home page.</li>
    </ul>
  </body>
</html>

Added UPGRADING.html.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>WebCalendar Upgrading Notes</title>
    <style type="text/css">
      body {
        background: #FFF;
        font-family: Arial, Helvetica, sans-serif;
      }
      a {
        text-decoration: none;
      }
      p {
        margin: 10px;
      }
      dl,
      ul {
        margin-left: 10px;
      }
      h2,
      h3 {
        padding: 5px;
      }
      h2 {
        background: #191970;
        color: #FFF;
      }
      dt {
        margin-top: 10px;
        font-weight: bold;
      }
      pre {
        margin-right: 25px;
        margin-left: 25px;
        border: 1px solid #00F;
        padding: 4px;
        background: #EEF;
        font-size: 14px;
        font-family: courier, monospace;
      }
      .tip {
        padding: 2px;
        background: #FF0;
        font-weight: bold;
      }
      .note {
        padding: 2px;
        background: #87CEFA;
        font-weight: bold;
      }
      hr {
        margin-bottom: 7px;
      }
      .valid {
        border: 0;
      }
      .top {
        text-align: right;
      }
    </style>
  </head>
  <body>
    <h1>WebCalendar Upgrading Notes</h1>

    <table border="0" style="margin-left: 50px;">
    <tr><th style="text-align: right;">WebCalendar Version:</th><td> 1.2.7 </td></tr>
    <tr><th valign="top" style="text-align: right;">Document Version:</th><td> $Revision: 1.43.2.15 $ <br/> $Date: 2013/02/22 15:56:47 $</td>
    </table>

    <p style="margin-bottom: 0"><span class="note">Important News:</span> A major
    improvement beginning with Version 1.1 is the addition of an automated
    installation script. This script will guide you through the installation
    process and help identify any problem areas that might prevent successful
    installation or operation of WebCalendar.</p>

    <ul style="margin-top: 0">
      <li style="margin-left: 30px">If upgrading, the script will attempt to
      determine your current installation version and bring your database up to
      date.</li>

      <li style="margin-left: 30px">If this is a new installation, the
      installation script will create your database and setup the required
      tables for you. It can then create a default Administrator account and
      add the basic configuration data to get you up and running.</li>
    </ul>

    <p>This installation script was tested primarily using MySQL and Apache on a
    dedicated server. If using an ISP or a CPANEL installer, your mileage may
    vary. If problems arise, you can always follow the instruction below as in
    previous versions and setup your database manually. As with any upgrade,
    it's always a good idea to <span style="color: #F00">backup your data prior
    to installation</span>.</p>

    <p>Another major upgrade to WebCalendar for v1.1 is the implementation of
    full timezone support. In previous versions, all date/time data was stored
    based on server time and users set their 'time offset' relative to server
    time. Now, all date/time data will be stored in the database as
    Greenwich Mean Time (GMT) and users will be able to select a timezone based
    on their geographical location.</p>

    <p>Having true timezone information available within WebCalendar enables the
    system to correct for Daylight Savings Time (DST) even if users are in
    different timezones. The database houses timezone information from 1970 to
    2038 and can calculate the appropriate GMT offset required to allow users to
    see events in their true 'local time'.</p>

    <p>The installation script will perform the initial import of the timezone
    data and guide you through the one-time conversion required to get your
    existing data converted to GMT.</p>

    <p><a href="install/index.php">Launch the Automatic Installation Script</a></p>

    <h2>Upgrading Steps</h2>

    <p>With the new 1.1 install wizard, you will no longer have to be troubled
    with uploading SQL files to phpMyAdmin or executing SQL commands yourself.
    Your database will be upgraded automatically from your current older
    WebCalendar installation.  Follow the steps below to upgrade to WebCalendar
    1.1 from an older version of WebCalendar.
    </p>

    <ol>
       <li>Make a backup of your current WebCalendar database.  This can be done
       a couple of different ways.
         <ul>
           <li>If you have access to phpMyAdmin, you can use the export function:
             <ul>
               <li>Startup phpMyAdmin </li>
               <li>Select the database from the pulldown on the left under the
                   label "Databases".  (This will be the same database name
                   used in your <tt>includes/settings.php</tt> file in your
                   old WebCalendar install.)</li>
               <li>Click on the "Export" tab.</li>
               <li>It's best to use "SQL" for the format so it can be easily imported again.</li>
               <li>Select "zipped" for compression.  If you don't do this, you will just
                   see the SQL in your browser window, and you will have to cut and
                   paste this into a text editor to save it.
               <li>Click on the "Go" button at the bottom of the page. </li>

             </ul> </li>
          <li>If you have access to a MySQL command line (typically via shell access on a
              Linux server), you can use the mysqldump command:<br/>
             &nbsp;&nbsp;<tt>mysqldump -u<b>USERNAME</b> -p<b>PASSWORD</b> <b>DATABASE</b> > dumpfile.sql</tt>
             <br/>Of course, replace USERNAME, PASSWORD and DATABASE from the values in
            your <tt>includes/settings.php</tt> file from your old WebCalendar install.
         </li>
         </ul></li>
       </li>

    <li>Make a backup of your current WebCalendar files on the server.  You would typically
        do this with an FTP client
        (like <a href="http://filezilla.sourceforge.net/">FileZilla</a>).
    </li>

    <li>Install the new WebCalendar files in a <b>new</b> directory on your server.
        How you do this will depend on what type of access you have to your server.
        It is best to not overwrite your old WebCalendar install.  The unpacked/unzipped
        files will create a directory with the current WebCalendar version name in it.
    </li>
    <li><b>Optional:</b>
        If you prefer to use a simple name (like "webcalendar" rather than "WebCalendar-1.1.6"),
        then you can rename the directory after you've installed the files.
        A good way to do this might be to rename your old webcalendar install to
        something like "webcalendar-oldinstall" and rename the new install to be
        the same name as your old one.
        <br/><b>Note:</b> If you are planning on renaming the directory, it is best to do
        this <i>before</i> you proceed to the automated install.
    </li>

    <li>Change the permissions the permissions of the <tt>includes</tt> directory.
        If you are doing this from FTP, change directories to the new webcalendar directory
        and use the following command:<br/>
        &nbsp;&nbsp;<tt>chmod 777 includes</tt>
    <li>Change the permissions the permissions of the <tt>icons</tt> directory.
        If you are doing this from FTP, change directories to the new webcalendar directory
        and use the following command:<br/>
        &nbsp;&nbsp;<tt>chmod 777 icons</tt>

    <li>Download a copy of your old <tt>includes/settings.php</tt> file from the old
        WebCalendar install and have it handy so you can enter the same values in your
        upgrade process. </li>
    <li>Download all files in your old <tt>icons</tt> directory from your old
        WebCalendar and copy the files into the <tt>icons</tt> directory in
        the new install directory. </li>

   <li>You're now ready to start the install/upgrade wizard.  Point your browser to the
       web server where you have installed the files.   You only need to specify
       the webcalendar directory to get to the wizard.  Because there is no
       <tt>includes/settings.php</tt> file in the new install, you will be redirected
       to the install/upgrade wizard.</li>
    
   <li>Once the wizard is complete, it's a good idea to change your <tt>includes</tt>
       permissions back to what they were originally for better security. </li>
    </ol>

    <hr />
    <h2>Manual Upgrade Instructions</h2>

    <p>Below are the steps needed to manually upgrade from a previous version.
    <b>You can ignore everything below if you use the Automated Installation
    Script.</b>  Select the version of your existing install from the list below.
    If you are more than one version behind (i.e. the new version is v1.1.6,
    and you're using 0.9.39), click the "next..." link at the end of each
    section to move to the next version.
    Always follow the versions in sequence.</p>

    <p><span class="note">Note:</span> Due to large number of database types
    that WebCalendar can support, it would be impractical to list all the SQL
    variations here. All SQL listed is taken from the
    <a href="install/sql/upgrade-mysql.sql" target="_blank">upgrade-mysq.sql</a>
    file used during the automatic installation process. If you are using a
    database other then MySQL, you may want refer to the appropriate
    upgrade-xxxxx.sql file in the install/sql folder.</p>

    <h2>My previous install was...</h2>

    <ul>
      <li><a href="UPGRADING.html#from_1.1.0a-CVS">1.1.0-CVS or 1.1.0a-CVS</a></li>
      <li><a href="UPGRADING.html#from_1.0.0">1.0RC3 or 1.0.0</a></li>
      <li><a href="UPGRADING.html#from_1_0RC2">0.9.45, 1.0RC1 or 1.0RC2</a></li>
      <li><a href="UPGRADING.html#dot944">0.9.44</a></li>
      <li><a href="UPGRADING.html#dot943">0.9.43</a></li>
      <li><a href="UPGRADING.html#dot942">0.9.42</a></li>
      <li><a href="UPGRADING.html#dot941">0.9.41</a></li>
      <li><a href="UPGRADING.html#dot940">0.9.40</a></li>
      <li><a href="UPGRADING.html#dot939">0.9.39</a></li>
      <li><a href="UPGRADING.html#dot938">0.9.38</a></li>
      <li><a href="UPGRADING.html#dot937">0.9.37</a></li>
      <li><a href="UPGRADING.html#dot936">0.9.35 - 0.9.36</a></li>
      <li><a href="UPGRADING.html#dot934">0.9.27 - 0.9.34</a></li>
      <li><a href="UPGRADING.html#dot926">0.9.22 - 0.9.26</a></li>
      <li><a href="UPGRADING.html#dot921">0.9.14 - 0.9.21</a></li>
      <li><a href="UPGRADING.html#dot913">0.9.12 - 0.9.13</a></li>
      <li><a href="UPGRADING.html#dot911">0.9.07 - 0.9.11</a></li>
      <li><a href="UPGRADING.html#dot906">0.9.01 - 0.9.06</a></li>
      <li><a href="UPGRADING.html#dot9">0.9</a></li>
    </ul>

    <hr />
    <h2><a id="dot9">To upgrade from v0.9</a></h2>

    <p>You need to create the table cal_user_pref in tables.sql. You need to
    create the table cal_entry_user in tables.sql that was mistakenly created as
    "cal_event_user" in the 0.9 release.</p>

    <a href="UPGRADING.html#dot906">next...</a>
    <hr />

    <h2><a id="dot906">To upgrade from v0.9.01</a></h2>

    <p>Entirely new tables are used. Use the following commands to convert your
    existing MySQL tables to the new tables:</p>

    <pre>
cd tools
./upgrade_to_0.9.7.pl
mysql intranet &lt; commands.sql
    </pre>

    <p>where "intranet" is the name of the MySQL database that contains your
    WebCalendar tables.</p>

    <a href="UPGRADING.html#dot911">next...</a>
    <hr />

    <h2><a id="dot911">To upgrade from v0.9.07 - v0.9.11</a></h2>

    <p>To fix a bug in the handing of events at midnight, all the entries with
    NULL for cal_time are changed to -1. Use the following SQL command:</p>

    <pre>UPDATE webcal_entry SET cal_time = -1 WHERE cal_time is null;</pre>

    <a href="UPGRADING.html#dot913">next...</a>
    <hr />

    <h2><a id="dot913">To upgrade from v0.9.12 or v0.9.13</a></h2>

    <p>A new table was added to support repeating events. Use the following SQL
    command:</p>

    <pre>
CREATE TABLE webcal_entry_repeats (
  cal_id INT DEFAULT '0' NOT NULL,
  cal_days CHAR(7),
  cal_end INT,
  cal_frequency INT DEFAULT '1',
  cal_type VARCHAR(20),
  PRIMARY KEY (cal_id)
);
    </pre>

    <a href="UPGRADING.html#dot921">next...</a>
    <hr />

    <h2><a id="dot921">To upgrade from v0.9.14 - v0.9.21</a></h2>

    <p>A new table was added to support layering. For MySQL, the SQL is:</p>

    <pre>
CREATE TABLE webcal_user_layers (
  cal_login varchar(25) NOT NULL,
  cal_layeruser varchar(25) NOT NULL,
  cal_color varchar(25) NULL,
  cal_dups CHAR(1) DEFAULT 'N',
  cal_layerid INT DEFAULT '0' NOT NULL,
  PRIMARY KEY ( cal_login, cal_layeruser )
);
    </pre>

    <a href="UPGRADING.html#dot926">next...</a>
    <hr />

    <h2><a id="dot926">To upgrade from v0.9.22 - v0.9.26</a></h2>

    <p>Two new tables were added for custom event fields and reminders.
    For MySQL the SQL is:</p>

    <pre>
CREATE TABLE webcal_site_extras (
  cal_id INT DEFAULT '0' NOT NULL,
  cal_name VARCHAR(25) NOT NULL,
  cal_type INT NOT NULL,
  cal_date INT DEFAULT '0',
  cal_remind INT DEFAULT '0',
  cal_data TEXT,
  PRIMARY KEY ( cal_id, cal_name, cal_type )
);
CREATE TABLE webcal_reminder_log (
  cal_id INT DEFAULT '0' NOT NULL,
  cal_name VARCHAR(25) NOT NULL,
  cal_event_date INT NOT NULL DEFAULT 0,
  cal_last_sent INT NOT NULL DEFAULT 0,
  PRIMARY KEY ( cal_id, cal_name, cal_event_date )
);
    </pre>

    <p>You will also need to setup the tools/send_reminders.php script to be run
    periodically. I would recommend once an hour. For Linux/UNIX, this is
    simple. Just use cron and add a line to your crontab file that looks like:</p>

    <pre>1 * * * * cd /some/directory/webcalendar/tools; ./send_reminders.php</pre>

    <p>This will tell cron to run the script at one minute after the hour.
    Windows users will have to find another way to run the script. There are
    ports/look-a-likes of cron for Windows, so look around.</p>

    <a href="UPGRADING.html#dot934">next...</a>
    <hr />

    <h2><a id="dot934">To upgrade from v0.9.27 - v0.9.34</a></h2>

    <p>Six new tables were added for group support, views, system settings and
    activity logs. For MySQL the SQL is:</p>

    <pre>
CREATE TABLE webcal_group (
  cal_group_id INT NOT NULL,
  cal_last_update INT NOT NULL,
  cal_name VARCHAR(50) NOT NULL,
  cal_owner VARCHAR(25) NULL,
  PRIMARY KEY ( cal_group_id )
);
CREATE TABLE webcal_group_user (
  cal_group_id INT NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  PRIMARY KEY ( cal_group_id, cal_login )
);
CREATE TABLE webcal_view (
  cal_view_id INT NOT NULL,
  cal_name VARCHAR(50) NOT NULL,
  cal_owner VARCHAR(25) NOT NULL,
  cal_view_type CHAR(1),
  PRIMARY KEY ( cal_view_id )
);
CREATE TABLE webcal_view_user (
  cal_view_id INT NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  PRIMARY KEY ( cal_view_id, cal_login )
);
CREATE TABLE webcal_config (
  cal_setting VARCHAR(50) NOT NULL,
  cal_value VARCHAR(50) NULL,
  PRIMARY KEY ( cal_setting )
);
CREATE TABLE webcal_entry_log (
  cal_log_id INT NOT NULL,
  cal_date INT NOT NULL,
  cal_entry_id INT NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  cal_time INT NULL,
  cal_type CHAR(1) NOT NULL,
  cal_text TEXT,
  PRIMARY KEY ( cal_log_id )
);
    </pre>

    <a href="UPGRADING.html#dot936">next...</a>
    <hr />

    <h2><a id="dot936">To upgrade from v0.9.35 or v0.9.36</a></h2>

    <p>The webcal_entry_log table was modified, and a new table
webcal_entry_repeats_not was created. Use the following SQL for MySQL:</p>

    <pre>
ALTER TABLE webcal_entry_log ADD cal_user_cal VARCHAR(25);
CREATE TABLE webcal_entry_repeats_not (
  cal_id INT NOT NULL,
  cal_date INT NOT NULL,
  PRIMARY KEY ( cal_id, cal_date )
);
    </pre>

    <a href="UPGRADING.html#dot937">next...</a>
    <hr />

    <h2><a id="dot937">To upgrade from v0.9.37</a></h2>

    <p>The webcal_entry_user table was modified, and a new table
    webcal_categories was created. Use the following SQL for MySQL:</p>

    <pre>
ALTER TABLE webcal_entry_user ADD cal_category INT DEFAULT NULL;
CREATE TABLE webcal_categories (
  cat_id INT NOT NULL,
  cat_name VARCHAR(80) NOT NULL,
  cat_owner VARCHAR(25),
  PRIMARY KEY ( cat_id )
);
    </pre>

    <a href="UPGRADING.html#dot938">next...</a>
    <hr />

    <h2><a id="dot938">To upgrade from v0.9.38</a></h2>

    <p>The names of the date settings in the database were modified. All old
    data settings need to be removed from the database.</p>

    <pre>
DELETE FROM webcal_config WHERE cal_setting LIKE 'DATE_FORMAT%';
DELETE FROM webcal_user_pref WHERE cal_setting LIKE 'DATE_FORMAT%';
    </pre>

    <a href="UPGRADING.html#dot939">next...</a>
    <hr />

    <h2><a id="dot939">To upgrade from v0.9.39</a></h2>

    <p>Two new tables were created: webcal_asst and webcal_entry_ext_user.
    And the column cal_ext_for_id was added to the webcal_entry table. Use the
    following SQL for MySQL:</p>

    <pre>
CREATE TABLE webcal_asst (
  cal_boss VARCHAR(25) NOT NULL,
  cal_assistant VARCHAR(25) NOT NULL,
  PRIMARY KEY ( cal_boss, cal_assistant )
);
CREATE TABLE webcal_entry_ext_user (
  cal_id INT DEFAULT 0 NOT NULL,
  cal_fullname VARCHAR(50) NOT NULL,
  cal_email VARCHAR(75) NULL,
  PRIMARY KEY ( cal_id, cal_fullname )
);
ALTER TABLE webcal_entry ADD cal_ext_for_id INT NULL;
    </pre>

    <a href="UPGRADING.html#dot940">next...</a>
    <hr />

    <h2><a id="dot940">To upgrade from v0.9.40</a></h2>

    <p>One new table was added: webcal_nonuser_cals. Use the following SQL for
    MySQL:</p>

    <pre>
CREATE TABLE webcal_nonuser_cals (
  cal_login VARCHAR(25) NOT NULL,
  cal_admin VARCHAR(25) NOT NULL,
  cal_firstname VARCHAR(25),
  cal_lastname VARCHAR(25),
  PRIMARY KEY ( cal_login )
);
    </pre>

    <a href="UPGRADING.html#dot941">next...</a>
    <hr />

    <h2><a id="dot941">To upgrade from v0.9.41</a></h2>

    <p>Three new tables were added: webcal_report, webcal_report_template, and
    webcal_import_data. Use the following SQL for MySQL:</p>

    <pre>
CREATE TABLE webcal_report (
  cal_report_id INT NOT NULL,
  cal_allow_nav CHAR(1) DEFAULT 'Y',
  cal_cat_id INT NULL,
  cal_include_empty CHAR(1) DEFAULT 'N',
  cal_include_header CHAR(1) DEFAULT 'Y' NOT NULL,
  cal_is_global CHAR(1) DEFAULT 'N' NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  cal_report_name VARCHAR(50) NOT NULL,
  cal_report_type VARCHAR(20) NOT NULL,
  cal_show_in_trailer CHAR(1) DEFAULT 'N',
  cal_time_range INT NOT NULL,
  cal_update_date INT NOT NULL,
  cal_user VARCHAR(25) NULL,
  PRIMARY KEY ( cal_report_id )
);
CREATE TABLE webcal_report_template (
  cal_report_id INT NOT NULL,
  cal_template_type CHAR(1) NOT NULL,
  cal_template_text TEXT,
  PRIMARY KEY ( cal_report_id, cal_template_type )
);
CREATE TABLE webcal_import_data (
  cal_id int NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  cal_external_id VARCHAR(200) NULL,
  cal_import_type VARCHAR(15) NOT NULL,
  PRIMARY KEY  ( cal_id, cal_login )
);
    </pre>

    <a href="UPGRADING.html#dot942">next...</a>
    <hr />

    <h2><a id="dot942">To upgrade from v0.9.42</a></h2>

    <p>User passwords are now stored using md5 and require the webcal_user table
    to be altered to accommodate larger password data. Use the following SQL
    for MySQL:</p>

    <pre>
ALTER TABLE webcal_user MODIFY cal_passwd VARCHAR(32) NULL;
DROP TABLE webcal_import_data;
CREATE TABLE webcal_import (
  cal_import_id INT NOT NULL,
  cal_date INT NOT NULL,
  cal_login VARCHAR(25) NULL,
  cal_name VARCHAR(50) NULL,
  cal_type VARCHAR(10) NOT NULL,
  PRIMARY KEY ( cal_import_id )
);
CREATE TABLE webcal_import_data (
  cal_id INT NOT NULL,
  cal_login VARCHAR(25) NOT NULL,
  cal_external_id VARCHAR(200) NULL,
  cal_import_id INT NOT NULL,
  cal_import_type VARCHAR(15) NOT NULL,
  PRIMARY KEY  ( cal_id, cal_login )
);
    </pre>

    <p>Next, you will need to run the script found in the <tt>tools</tt>
    subdirectory. This will convert all your passwords from plain text to md5.
    You can run this from the command line (if you have a standalone version of
    PHP compiled):</p>

    <pre>
cd tools
php convert_passwords.php
    </pre>

    <p>Or, if you do not have a standalone version of PHP, you can just type in
    the URL to access the script in your browser:</p>

    <pre>http://yourcalendarurl/tools/convert_passwords.php</pre>

    <p>You may safely delete the file <tt>/tools/convert_passwords.php</tt>
    after successfully performing this step.</p>

    <p>Delete all webcalendar_login browser cookies. Details should be available
    on your local browser help section.</p>

    <a href="UPGRADING.html#from_1_0RC2">next...</a>
    <hr />

    <h2><a id="from_1_0RC2">To upgrade from v0.9.43 - v1.0RC2</a></h2>

    <p>The <tt>webcal_view</tt> table was modified. Execute the following SQL
    to update your database:</p>

    <pre>
UPDATE webcal_config SET cal_value = 'week.php' WHERE cal_setting = 'STARTVIEW';
UPDATE webcal_user_pref SET cal_value = 'day.php'
  WHERE cal_value = 'day' AND cal_setting = 'STARTVIEW';
UPDATE webcal_user_pref SET cal_value = 'month.php'
  WHERE cal_value = 'month' AND cal_setting = 'STARTVIEW';
UPDATE webcal_user_pref SET cal_value = 'week.php'
  WHERE cal_value = 'week' AND cal_setting = 'STARTVIEW';
UPDATE webcal_user_pref SET cal_value = 'year.php'
  WHERE cal_value = 'year' AND cal_setting = 'STARTVIEW';
ALTER TABLE webcal_view ADD cal_is_global CHAR(1) NOT NULL DEFAULT 'N';
UPDATE webcal_view SET cal_is_global = 'N';
    </pre>

    <a href="UPGRADING.html#from_1.0.0">next...</a>
    <hr />

    <h2><a id="from_1.0.0">To upgrade from v1.0RC3 - v1.0.0</a></h2>

    <p>Two new tables need to be created to support advanced user access control.
    One new table is needed to store custom user header/footer template
    information. Execute the following SQL to update your database:</p>

    <pre>
CREATE TABLE webcal_access_user (
  cal_login VARCHAR(25) NOT NULL,
  cal_other_user VARCHAR(25) NOT NULL,
  cal_can_approve CHAR(1) NOT NULL DEFAULT 'N',
  cal_can_delete CHAR(1) NOT NULL DEFAULT 'N',
  cal_can_edit CHAR(1) NOT NULL DEFAULT 'N',
  cal_can_view CHAR(1) NOT NULL DEFAULT 'N',
  PRIMARY KEY ( cal_login, cal_other_user )
);
CREATE TABLE webcal_access_function (
  cal_login VARCHAR(25) NOT NULL,
  cal_permissions VARCHAR(64) NOT NULL,
  PRIMARY KEY ( cal_login )
);
ALTER TABLE webcal_nonuser_cals ADD cal_is_public CHAR(1) NOT NULL DEFAULT 'N';
CREATE TABLE webcal_user_template (
  cal_login VARCHAR(25) NOT NULL,
  cal_type CHAR(1) NOT NULL,
  cal_template_text TEXT,
  PRIMARY KEY ( cal_login, cal_type )
);
    </pre>

    <hr />

    <h2><a id="from_1.1.0a-CVS">To upgrade from v1.1.0-CVS or v1.1.0a-CVS</a></h2>

    <p>A new table is needed to support multiple categories. In addition,
    several new columns have been added to webcal_entry and one column added to
    webcal_entry_user to support VTODO tasks, and to webcal_repeats to support
    the much improved ical support. A new column was added to
    webcal_entry_repeats_not to differentiate between exclusion and inclusions.
    Use the following SQL to update your MySQL database:</p>

    <pre>
ALTER TABLE webcal_entry ADD cal_due_date int(11) default NULL;
ALTER TABLE webcal_entry ADD cal_due_time int(11) default NULL;
ALTER TABLE webcal_entry ADD cal_location varchar(50) default NULL;
ALTER TABLE webcal_entry ADD cal_url varchar(100) default NULL;
ALTER TABLE webcal_entry ADD cal_completed int(11) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_endtime int(11) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_byday varchar(100) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_bymonth varchar(50) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_bymonthday varchar(100) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_bysetpos varchar(50) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_byweekno varchar(50) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_byyearday varchar(50) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_count int(11) default NULL;
ALTER TABLE webcal_entry_repeats ADD cal_wkst char(2) default 'MO';
ALTER TABLE webcal_entry_repeats_not ADD cal_exdate int(1) NOT NULL DEFAULT '1';
ALTER TABLE webcal_entry_user ADD cal_percent int(11) NOT NULL DEFAULT '0';
CREATE TABLE webcal_entry_categories (
  cal_id int(11) NOT NULL default '0',
  cat_id int(11) NOT NULL default '0',
  cat_order int(11) NOT NULL default '0',
  cat_owner varchar(25) default NULL
);
    </pre>

    <hr />

    <p>After you complete manually updating your database, you will still need
    to run the <a href="install/index.php">installation script</a> to perform
    any necessary data changes needed to convert existing data.</p>

    <p><a href="http://validator.w3.org/check?uri=referer">
      <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!"
      class="valid" /></a></p>
  </body>
</html>

Added about.php.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
/* $Id: about.php,v 1.16.2.3 2007/08/06 02:28:29 cknudsen Exp $ */
include_once 'includes/init.php';

$credits = getPostValue ( 'Credits' );
$data = '';

if ( ! empty ( $credits ) ) {
  // Get Names from AUTHORS file.
  if ( $fd = @fopen ( 'AUTHORS', 'r' ) ) {
    // Read in contents of entire file first.
    while ( ! feof ( $fd ) && empty ( $error ) ) {
      $data .= fgets ( $fd, 4096 );
    }
    fclose ( $fd );
  }
  // $data = unhtmlentities ( $data );
  $data = preg_replace ( '/<.+>+/', '', $data );
  $data = preg_replace ( "/\n\s/", '<br />&nbsp;', $data );
  $data = preg_replace ( '/\s\s+/', '&nbsp;&nbsp;', $data );
  $data = preg_replace ( '/\n/', '<br />', $data );
}

print_header ( '', '', '', true, false, true );
echo '
    <div align="left" style="margin-left:4px; position:absolute; bottom:0">';
if ( empty ( $credits ) )
  echo '
      <a title="' . $PROGRAM_NAME . '" href="' . $PROGRAM_URL . '" target="_blank">
      <h2 style="margin:0">' . translate ( 'Title' ) . '</h2>
      <p>' . str_replace ( 'XXX', $PROGRAM_VERSION,
        // translate ( 'version' )
        translate ( 'version XXX' ) ) . '</p>
      <p>' . $PROGRAM_DATE . '</p></a>
      <p>&nbsp;</p>
      <p>' . translate ( 'WebCalendar is a PHP application used...' ) . '</p>';
else {

  ?>
      <script language="javascript1.2" type="text/javascript">
        var
          scrollW="235px",
          scrollH="250px",
          copyS=scrollS=1,
          pauseS=0,
          scrollcontent='<?php echo $data ?>',
          actualH='',
          cross_scroll;

        function populate (){
          cross_scroll=document.getElementById("scroller");
          cross_scroll.innerHTML=scrollcontent;
          actualH=cross_scroll.offsetHeight;
          lefttime=setInterval("scrollMe ()",30);
        }

        window.onload=populate;

        function scrollMe (){
          if (parseInt (cross_scroll.style.top)>(actualH* (-1)+8))
            cross_scroll.style.top=parseInt(cross_scroll.style.top)-copyS+"px";
          else
            cross_scroll.style.top=parseInt(scrollH)+8+"px";
        }

        with (document){
          write('<div style="position:relative; width:'+scrollW+'; height: '
            + scrollH +'; overflow:hidden;" onMouseover="copyS=pauseS" '
            + 'onMouseout="copyS=scrollS"><div id="scroller"></div></div>');
        }
      </script>
<?php
}

echo '
      <hr />
      <div align="center" style="margin:10px;">
        <form action="about.php" name="aboutform" method="post">
          <input type="submit" name=' . ( empty ( $credits )
  ? '"Credits" value="' . translate ( 'Credits' )
  : '"About" value="<< ' . translate ( 'About' ) )
 . '" />' . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
          <input type="button" name="ok" value="' . translate ( 'OK' )
 . '" onclick="window.close()" />
        </form>
      </div>
    </div>
    ' . print_trailer ( false, true, true );

?>

Added access.php.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
<?php
/* $Id: access.php,v 1.53.2.7 2012/02/28 02:07:45 cknudsen Exp $
 *
 * This page is used to manage user access rights.
 *
 * It has three different modes:
 * - list users to manage (no parameters)
 * - manage a single user's rights (just "user" parameter)
 *   this will include which functions the user can access and
 *   (if $ALLOW_VIEW_OTHER is 'Y') which calendars thay can view/edit/approve
 * - update the database (form handler)
 *
 * Input Parameters:
 *  user - specifies which user to manage, a form will be presented
 *         that allows editing rights of this user
 *
 *  access_N - where N is 0 to ACCESS_NUMBER_FUNCTIONS as defined in
 *             includes/access.php. Each should be either 'Y' or 'N'.
 */
include_once 'includes/init.php';
require_valide_referring_url ();

$allow_view_other =
( ! empty ( $ALLOW_VIEW_OTHER ) && $ALLOW_VIEW_OTHER == 'Y' );

if ( ! access_is_enabled () ) {
  echo print_not_auth (1);
  exit;
}
// translate ( 'Database error' )
$dbErrStr = translate ( 'Database error XXX.' );
$defConfigStr = translate ( 'DEFAULT CONFIGURATION' );
$goStr = '
      </select>
      <input type="submit" value="' . translate ( 'Go' ) . '" />
    </form>';
$saveStr = translate ( 'Save' );
$undoStr = translate ( 'Undo' );

$saved = '';

// Are we handling the access form?
// If so, do that, then redirect.
// Handle function access first.
if ( getPostValue ( 'auser' ) != '' &&
    getPostValue ( 'submit' ) == $saveStr ) {
  $auser = getPostValue ( 'auser' );
  $perm = '';
  for ( $i = 0; $i < ACCESS_NUMBER_FUNCTIONS; $i++ ) {
    $perm .= ( getPostValue ( 'access_' . $i ) == 'Y' ? 'Y' : 'N' );
  }

  dbi_execute ( 'DELETE FROM webcal_access_function WHERE cal_login = ?',
    array ( $auser ) );

  if ( ! dbi_execute ( 'INSERT INTO webcal_access_function ( cal_login,
      cal_permissions ) VALUES ( ?, ? )', array ( $auser, $perm ) ) )
    die_miserable_death ( str_replace ( 'XXX', dbi_error (), $dbErrStr ) );
  $saved = true;
}

// Are we handling the other user form?  If so, do that, then redirect.
if ( getPostValue ( 'otheruser' ) != '' &&
    getPostValue ( 'submit' ) == $saveStr ) {
  $puser = getPostValue ( 'guser' );
  $pouser = getPostValue ( 'otheruser' );

  if ( $allow_view_other ) {
    // Handle access to other users' calendars.
    // If user is not admin,
    // reverse values so they are granting access to their own calendar.
    if ( ! $is_admin )
      list ( $puser, $pouser ) = array ( $pouser, $puser );

    dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
      AND cal_other_user = ?', array ( $puser, $pouser ) );

    if ( empty ( $pouser ) )
      break;
    $approve_total = $edit_total = $view_total = 0;
    for ( $i = 1; $i <= 256; ) {
      $approve_total += getPostValue ( 'a_' . $i );
      $edit_total += getPostValue ( 'e_' . $i );
      $view_total += getPostValue ( 'v_' . $i );
      $i += $i;
    }

    $email = getPostValue ( 'email' );
    $invite = getPostValue ( 'invite' );
    $time = getPostValue ( 'time' );

    if ( ! dbi_execute ( 'INSERT INTO webcal_access_user ( cal_login,
      cal_other_user, cal_can_view, cal_can_edit, cal_can_approve,
      cal_can_invite, cal_can_email, cal_see_time_only )
      VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )',
        array (
          $puser,
          $pouser,
          ( $view_total > 0 ? $view_total : 0 ),
          ( $edit_total > 0 && $puser != '__public__' ? $edit_total : 0 ),
          ( $approve_total > 0 && $puser != '__public__' ? $approve_total : 0 ),
          ( strlen ( $invite ) ? $invite : 'N' ),
          ( strlen ( $email ) ? $email : 'N' ),
          ( strlen ( $time ) ? $time : 'N' ) ) ) ) {
      die_miserable_death ( str_replace ( 'XXX', dbi_error (), $dbErrStr ) );
    }
    $saved = true;
  }
}
$checked = ' checked="checked"';
$guser = getPostValue ( 'guser' );
$selected = ' selected="selected"';

//if ( $guser == '__default__' ) {
//  $otheruser = $guser;
//  $user_fullname = $defConfigStr;
//} else
  $otheruser = getPostValue ( 'otheruser' );

if ( $otheruser == '__default__' ) {
  $otheruser_fullname = $defConfigStr;
  $otheruser_login = '__default__';
} elseif ( $otheruser == '__public__' ) {
  $otheruser_fullname = translate ( 'Public Access' );
  $otheruser_login = '__public__';
}
if ( ! empty ( $otheruser ) ) {
  if ( $allow_view_other ) {
    user_load_variables ( $otheruser, 'otheruser_' );
    // Turn off admin override so we see the users own settings.
    $ADMIN_OVERRIDE_UAC = 'N';
    // Now load all the data from webcal_access_user.
    $allPermissions = access_load_user_permissions ( false );
    // Load default-default values if exist.
    if ( ! empty ( $allPermissions['__default__.__default__'] ) )
      $op = $allPermissions['__default__.__default__'];

    if ( $is_admin ) {
      // Load user-default values if exist.
      if ( ! empty ( $allPermissions[ $guser . '.__default__' ] ) )
        $op = $allPermissions[ $guser . '.__default__' ];
      // Load user-otheruser values if exist.
      if ( ! empty ( $allPermissions[ $guser . '.' . $otheruser ] ) )
        $op = $allPermissions[ $guser . '.' . $otheruser ];
    } else {
      // Load defualt-user values if exist.
      if ( ! empty ( $allPermissions['__default__.' . $guser] ) )
        $op = $allPermissions['__default__.' . $guser ];
      // Load otheruser-user values if exist.
      if ( ! empty ( $allPermissions[$otheruser . '.' . $guser] ) )
        $op = $allPermissions[$otheruser . '.' . $guser];
    }
  }
}
print_header ( '', '',
  ( ! empty ( $op['time'] ) && $op['time'] == 'Y'
    ? 'onload="enableAll( true );"' : '' ) );

echo print_success ( $saved );

if ( ! empty ( $guser ) && $is_admin )
  user_load_variables ( $guser, 'user_' );

ob_start ();

if ( $is_admin ) {
  $adminStr = translate ( 'Admin' );
  $userlist = get_my_users ();
  $nonuserlist = get_nonuser_cals ();

  // If we are here... we must need to print out a list of users.
  echo '
    <h2>' . translate ( 'User Access Control' )
   . ( ! empty ( $user_fullname ) ? ': ' . $user_fullname : '' ) . '</h2>
    ' . display_admin_link ( false ) . '
    <form action="access.php" method="post" name="SelectUser">
      <select name="guser" onchange="document.SelectUser.submit()">'
  // Add a DEFAULT CONFIGURATION to be used as a mask.
  . '
        <option value="__default__"'
   . ( $guser == '__default__' ? $selected : '' )
   . '>' . $defConfigStr . '</option>';
  for ( $i = 0, $cnt = count ( $userlist ); $i < $cnt; $i++ ) {
    echo '
        <option value="' . $userlist[$i]['cal_login'] . '"'
     . ( $guser == $userlist[$i]['cal_login'] ? $selected : '' )
     . '>' . $userlist[$i]['cal_fullname'] . '</option>';
  }
  for ( $i = 0, $cnt = count ( $nonuserlist ); $i < $cnt; $i++ ) {
    echo '
        <option value="' . $nonuserlist[$i]['cal_login'] . '"'
     . ( $guser == $nonuserlist[$i]['cal_login'] ? $selected : '' )
     . '>' . $nonuserlist[$i]['cal_fullname'] . ' '
     . ( $nonuserlist[$i]['cal_is_public'] == 'Y' ? '*' : '' ) . '</option>';
  }

  echo $goStr;
} //end admin $guser != default test

if ( ! empty ( $guser ) || ! $is_admin ) {
  if ( $is_admin ) {
    // Present a page to allow editing a user's rights.
    $access = access_load_user_functions ( $guser );
    $div = ceil ( ACCESS_NUMBER_FUNCTIONS / 4 );

    // We can reorder the display of user rights here.
    $order = array (
      1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 27,
      15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 );
    // Make sure that we have defined all the types of
    // access defined in access.php
    assert ( count($order) == ACCESS_NUMBER_FUNCTIONS +1 );

    echo '
    <div class="boxall" style="margin-top: 5px; padding: 5px;">
      <form action="access.php" method="post" name="accessform">
        <input type="hidden" name="auser" value="' . $guser . '" />
        <input type="hidden" name="guser" value="' . $guser . '" />
        <table border="0" cellspacing="10">
          <tbody>
            <tr>
              <td valign="top">';

    for ( $i = 0; $i < ACCESS_NUMBER_FUNCTIONS; $i++ ) {
      // Public access and NUCs can never use some of these functions.
      $show = true;
      if ( $guser == '__public__' ||
        substr ( $guser, 0, 5 ) == $NONUSER_PREFIX ) {
        switch ( $order[$i] ) {
          case ACCESS_ACCESS_MANAGEMENT:
          case ACCESS_ACCOUNT_INFO:
          case ACCESS_ACTIVITY_LOG:
          case ACCESS_ADMIN_HOME:
          case ACCESS_ASSISTANTS:
          case ACCESS_CATEGORY_MANAGEMENT:
          case ACCESS_IMPORT:
          case ACCESS_PREFERENCES:
          case ACCESS_SYSTEM_SETTINGS:
          case ACCESS_USER_MANAGEMENT:
          case ACCESS_VIEW_MANAGEMENT:
          case ACCESS_SECURITY_AUDIT:
            // Skip these...
            $show = false;
            break;
        }
      }
      if ( $show )
        echo print_checkbox ( array ( 'access_' . $order[$i], 'Y',
            access_get_function_description ( $order[$i] ),
            substr ( $access, $order[$i], 1 ) ), 'dito' ) . '<br />';

      if ( ( $i + 1 ) % $div == 0 )
        echo '
              </td>
              <td valign="top">';
    }

    echo '
              </td>
            </tr>
          </tbody>
        </table>
        <input type="submit" value="' . $undoStr . '" />
        <input type="submit" name="submit" value="' . $saveStr . '" />
      </form>
    </div>';

    $pagetitle = translate ( 'Allow Access to Other Users Calendar' );
  } else {
    // Get list of users that this user can see (may depend on group settings)
    // along with all nonuser calendars.
    // if ( $guser != '__default__' ) {
    $guser = $login;
    $pagetitle = translate ( 'Grant This User Access to My Calendar' );
  }

//  if ( $guser == '__default__' ) {
//    $userlist = array ( '__default__' );
//    $otheruser = $otheruser_login = '__default__';
 //   $otheruser_fullname = $defConfigStr;
//  } else
  if ( $allow_view_other ) {
    $userlist = get_list_of_users ( $guser );
    echo '
    <h2 style="margin-bottom: 2px;">' . $pagetitle . '</h2>
    <form action="access.php" method="post" name="SelectOther">
      <input type="hidden" name="guser" value="' . $guser . '" />
      <select name="otheruser" onchange="document.SelectOther.submit()">'
    // Add a DEFAULT CONFIGURATION to be used as a mask.
    . '
        <option value="__default__"'
     . ( $otheruser == '__default__' ? $selected : '' )
     . '>' . $defConfigStr . '</option>';

    for ( $i = 0, $cnt = count ( $userlist ); $i < $cnt; $i++ ) {
      if ( $userlist[$i]['cal_login'] != $guser )
        echo '
        <option value="' . $userlist[$i]['cal_login'] . '"'
         . ( ! empty ( $otheruser ) && $otheruser == $userlist[$i]['cal_login']
          ? $selected : '' )
         . '>' . $userlist[$i]['cal_fullname'] . '</option>';
    }
    echo $goStr;
  }
}

if ( ! empty ( $otheruser ) ) {
  if ( $allow_view_other ) {
    $typeStr = translate ( 'Type' );
    echo '
    <form action="access.php" method="post" name="EditOther">
      <input type="hidden" name="guser" value="' . $guser . '" />
      <input type="hidden" name="otheruser" value="' . $otheruser . '" /><br />
      <table cellpadding="5" cellspacing="0">
        <tbody>
          <tr>
            <th class="boxleft boxtop boxbottom" width='
     . ( $guser == '__public__'
      ? '"60%" align="center">' . translate ( 'Calendar' ) . '</th>
            <th class="boxtop boxbottom" width="20%">' . $typeStr . '</th>
            <th class="boxtop boxbottom boxright" colspan="3" width="20%">'
       . translate ( 'View Event' )
      : '"25%">' . $otheruser_fullname . '</th>
            <th class="boxtop boxbottom" width="15%">' . $typeStr . '</th>
            <th width="15%" colspan="3" class="boxtop boxbottom">'
       . translate ( 'View' ) . '</th>
            <th width="15%" colspan="3" class="boxtop boxbottom">'
       . translate ( 'Edit' ) . '</th>
            <th width="15%" colspan="3" class="boxtop boxright boxbottom">'
       . translate ( 'Approve/Reject' ) ) . '</th>
          </tr>';

    $access_type = array (
      '',
      translate ( 'Events' ),
      translate ( 'Tasks' ),
      '',
      translate ( 'Journals' )
      );

    for ( $j = 1; $j < 5; $j++ ) {
      $bottomedge = '';
      if ( $j == 3 )
        continue;
      echo '
          <tr>
            <td class="boxleft leftpadded' . ( $j > 3 ? ' boxbottom' : '' )
       . '"><input type="checkbox" value="Y" name=';
      if ( $j == 1 )
        echo '"invite"'
         . ( ! empty ( $op['invite'] ) && $op['invite'] == 'N' ? '' : $checked )
         . ' />' . translate ( 'Can Invite' );
      elseif ( $j == 2 )
        echo '"email"'
         . ( ! empty ( $op['email'] ) && $op['email'] == 'N' ? '' : $checked )
         . ' />' . translate ( 'Can Email' );
      else {
        echo '"time"'
         . ( ! empty ( $op['time'] ) && $op['time'] == 'Y' ? $checked : '' )
         . ' onclick="enableAll( this.checked );" />'
         . translate ( 'Can See Time Only' );
        $bottomedge = 'boxbottom';
      }
      echo '</td>
            <td align="center" class="boxleft ' . $bottomedge . '">'
       . $access_type[$j] . '</td>
            <td align="center" class="boxleft pub ' . $bottomedge . '">'
       . '<input type="checkbox" value="' . $j . '" name="v_' . $j . '"'
       . ( ! empty ( $op['view'] ) && ( $op['view'] & $j ) ? $checked : '' )
       . ' /></td>
            <td class="conf ' . $bottomedge . '"><input type="checkbox" value="'
       . $j * 8 . '" name="v_' . $j * 8 . '"'
       . ( ! empty ( $op['view'] ) && ( $op['view'] & ( $j * 8 ) )
        ? $checked : '' ) . ' /></td>
            <td class="priv ' . $bottomedge . '"><input type="checkbox" value="'
       . $j * 64 . '" name="v_' . $j * 64 . '"'
       . ( ! empty ( $op['view'] ) && ( $op['view'] & ( $j * 64 ) )
        ? $checked : '' ) . ' /></td>'
       . ( $guser != '__public__' ? '
            <td align="center" class="boxleft pub ' . $bottomedge . '"><input '
         . 'type="checkbox" value="' . $j . '" name="e_' . $j . '"'
         . ( ! empty ( $op['edit'] ) && ( $op['edit'] & $j ) ? $checked : '' )
         . ' /></td>
            <td class="conf ' . $bottomedge . '"><input type="checkbox" value="'
         . $j * 8 . '" name="e_' . $j * 8 . '"'
         . ( ! empty ( $op['edit'] ) && ( $op['edit'] & ( $j * 8 ) )
          ? $checked : '' ) . ' /></td>
            <td class="priv ' . $bottomedge . '"><input type="checkbox" value="'
         . $j * 64 . '" name="e_' . $j * 64 . '"'
         . ( ! empty ( $op['edit'] ) && ( $op['edit'] & ( $j * 64 ) )
          ? $checked : '' ) . ' /></td>
            <td align="center" class="boxleft pub ' . $bottomedge . '"><input '
         . 'type="checkbox" value="' . $j . '" name="a_' . $j . '"'
         . ( ! empty ( $op['approve'] ) && ( $op['approve'] & $j )
          ? $checked : '' ) . ' /></td>
            <td class="conf ' . $bottomedge . '"><input type="checkbox" value="'
         . $j * 8 . '" name="a_' . $j * 8 . '"'
         . ( ! empty ( $op['approve'] ) && ( $op['approve'] & ( $j * 8 ) )
          ? $checked : '' ) . ' /></td>
            <td class="boxright priv ' . $bottomedge
         . '"><input type="checkbox" value="' . $j * 64 . '" name="a_' . $j * 64
         . '"' . ( ! empty ( $op['approve'] ) && ( $op['approve'] & ( $j * 64 ) )
          ? $checked : '' ) . ' /></td>'
        : '' ) . '
          </tr>';
    }
    echo '
          <tr>
            <td colspan="2" class="boxleft alignright">'
     . ( $otheruser != '__default__' && $otheruser != '__public__' ? '
              <input type="button" value="' . translate ( 'Assistant' )
       . '" onclick="selectAll(63);" />&nbsp;&nbsp;' : '' ) . '
              <input type="button" value="' . translate ( 'Select All' )
     . '" onclick="selectAll(256);" />&nbsp;&nbsp;
              <input type="button" value="' . translate ( 'Clear All' )
     . '" onclick="selectAll(0);" />
            </td>
            <td colspan="9" class="boxright">
              <table border="0" align="center" cellpadding="5" cellspacing="2">
                <tr>
                  <td class="pub">' . translate ( 'Public' ) . '</td>
                  <td class="conf">' . translate ( 'Confidential' ) . '</td>
                  <td class="priv">' . translate ( 'Private' ) . '</td>
                </tr>
              </table>
            </td>
          </tr>';
  }

  echo '
          <tr>
            <td colspan="11" class="boxleft boxbottom boxright">
              <input type="submit" value="' . $undoStr . '" />
              <input type="submit" name="submit" value="' . $saveStr . '" />
            </td>
          </tr>
        </tbody>
      </table>
    </form>';

  ob_end_flush ();

  ?>
    <script language="javascript" type="text/javascript">
<!-- <![CDATA[
      function selectAll ( limit ) {
        if ( limit == 0 )
          document.EditOther.time.checked = false;

        document.EditOther.email.checked =
        document.EditOther.invite.checked = ( limit != 0 )

        for ( i = 1; i <= 256; ) {
          var
            aname = 'a_' + i,
            ename = 'e_' + i,
            vname = 'v_' + i;

          document.forms['EditOther'].elements[vname].checked = (i <= limit);

          if (document.forms['EditOther'].elements[ename])
            document.forms['EditOther'].elements[ename].checked = (i <= limit);

          if (document.forms['EditOther'].elements[aname])
            document.forms['EditOther'].elements[aname].checked = (i <= limit);

          i = parseInt(i+i);
        }
      }
      function enableAll ( on ) {
        for ( i = 1; i <= 256; ) {
          var
            aname = 'a_' + i,
            ename = 'e_' + i,
            vname = 'v_' + i;

          document.forms['EditOther'].elements[vname].disabled = on;

          if (document.forms['EditOther'].elements[ename])
            document.forms['EditOther'].elements[ename].disabled = on;

          if (document.forms['EditOther'].elements[aname])
            document.forms['EditOther'].elements[aname].disabled = on;

          i = parseInt(i+i);
        }
      }
//]]> -->
    </script>
<?php
}

echo print_trailer ();
// Get the list of users that the specified user can see.
function get_list_of_users ( $user ) {
  global $is_admin, $is_nonuser_admin;
  //Let Admins userlist be returnd
  if ( $user == '__default__' )
    $user = '';
  $u = get_my_users ( $user, 'view' );
  if ( $is_admin || $is_nonuser_admin ) {
    // Get public NUCs also.
    $nonusers = get_my_nonusers ( $user, true );
    $u = array_merge ( $nonusers, $u );
  }
  return $u;
}

?>

Added activity_log.php.















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php
/* $Id: activity_log.php,v 1.53.2.3 2007/11/12 15:40:29 umcesrjones Exp $
 *
 * Description:
 *  Display either the "Activity Log" (for events/tasks) or the
 *  "System Log" (entries not associated with an event).
 *
 * Input Parameters:
 *  startid  - specified the id of the first log entry to display
 *  system   - if specified, then view the system log (entries with no
 *             event id associated with them) rather than the event log.
 *
 * Security:
 *  User must be an admin user
 *  AND, if user access control is enabled, they must have access to
 *  activity logs. (This is because users may see event details
 *  for other groups that they are not supposed to have access to.)
 */
include_once 'includes/init.php';

if ( ! $is_admin || ( access_is_enabled () && !
      access_can_access_function ( ACCESS_ACTIVITY_LOG ) ) )
  die_miserable_death ( print_not_auth (2) );

$eventsStr = translate ( 'Events' );
$nextStr = translate ( 'Next' );
$prevStr = translate ( 'Previous' );

$PAGE_SIZE = 25; // Number of entries to show at once.
$startid = getValue ( 'startid', '-?[0-9]+', true );
$sys = ( $is_admin && getGetValue ( 'system' ) != '' );

print_header ();

ob_start ();

echo generate_activity_log ( '', $sys, $startid );

echo '
    <div class="navigation">'
// Go BACK in time.
 . ( ! empty ( $nextpage ) ? '
      <a title="' . $prevStr . '&nbsp;' . $PAGE_SIZE . '&nbsp;' . $eventsStr
   . '" class="prev" href="activity_log.php?startid=' . $nextpage
   . ( $sys ? '&amp;system=1' : '' ) . '">' . $prevStr . '&nbsp;' . $PAGE_SIZE
   . '&nbsp;' . $eventsStr . '</a>' : '' );

if ( ! empty ( $startid ) ) {
  $previd = $startid + $PAGE_SIZE;
  $res = dbi_execute ( 'SELECT MAX( cal_log_id ) FROM webcal_entry_log' );
  if ( $res ) {
    if ( $row = dbi_fetch_row ( $res ) )
      // Go FORWARD in time.
      echo '
      <a title="' . $nextStr . '&nbsp;' . $PAGE_SIZE . '&nbsp;' . $eventsStr
       . '" class="next" href="activity_log.php' . ( $row[0] <= $previd
        ? ( $sys ? '?system=1' : '' )
        : '?startid=' . $previd . ( $sys ? '&amp;system=1' : '' ) ) . '">'
       . $nextStr . '&nbsp;' . $PAGE_SIZE . '&nbsp;' . $eventsStr . '</a><br />';

    dbi_free_result ( $res );
  }
}

ob_end_flush ();

echo '
    </div>
    ' . print_trailer ();

?>

Added add_entry.php.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
/* $Id: add_entry.php,v 1.29.2.2 2007/08/06 02:28:29 cknudsen Exp $ */
include_once 'includes/init.php';

$error = '';
// Only proceed if id was passed.
if ( $id > 0 ) {
  // Double check to make sure user doesn't already have the event.
  $is_my_event = $is_private = false;
  $res = dbi_execute ( 'SELECT cal_id FROM webcal_entry_user
    WHERE cal_login = ? AND cal_id = ?', array ( $login, $id ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    if ( $row[0] == $id ) {
      $is_my_event = true;
      echo str_replace ( 'XXX', $id,
        translate ( 'Event XXX is already on your calendar.' ) );
      exit;
    }
    dbi_free_result ( $res );
  }
  // Now lets make sure the user is allowed to add the event (not private).
  $res = dbi_execute ( 'SELECT cal_access FROM webcal_entry WHERE cal_id = ?',
    array ( $id ) );
  if ( ! $res ) {
    echo str_replace ( 'XXX', $id, translate ( 'Invalid entry id XXX.' ) );
    exit;
  }
  $mayNotAddStr =
  translate ( 'a XXX event may not be added to your calendar' );
  $row = dbi_fetch_row ( $res );

  if ( ! $is_my_event ) {
    if ( $row[0] == 'C' && ! $is_assistant && ! $is_nonuser_admin ) {
      // Assistants are allowed to see confidential stuff.
      $is_private = true;
      echo str_replace ( 'XXX', translate ( 'confidential' ), $mayNotAddStr );
      exit;
    } else
    if ( $row[0] == 'R' ) {
      $is_private = true;
      echo str_replace ( 'XXX', translate ( 'private' ), $mayNotAddStr );
      exit;
    }
  }
  // Add the event.
  if ( $readonly == 'N' && ! $is_my_event && ! $is_private ) {
    if ( ! dbi_execute ( 'INSERT INTO webcal_entry_user ( cal_id, cal_login,
      cal_status ) VALUES ( ?, ?, ? )', array ( $id, $login, 'A' ) ) )
      // translate ( 'Error adding event' )
      $error = str_replace ( 'XXX', dbi_error (),
        translate ( 'Error adding event XXX.' ) );
  }
}

send_to_preferred_view ();
exit;

?>

Added admin.php.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
<?php
/* $Id: admin.php,v 1.183.2.9 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();
include_once 'includes/date_formats.php';
if ( file_exists ( 'install/default_config.php' ) )
  include_once 'install/default_config.php';
// .
// Force the CSS cache to clear by incrementing webcalendar_csscache cookie.
// admin.php will not use this cached CSS, but we want to make sure it's flushed.
$webcalendar_csscache = 1;
if ( isset ( $_COOKIE['webcalendar_csscache'] ) )
  $webcalendar_csscache += $_COOKIE['webcalendar_csscache'];

SetCookie ( 'webcalendar_csscache', $webcalendar_csscache );

function save_pref ( $prefs, $src ) {
  global $error, $my_theme;

  while ( list ( $key, $value ) = each ( $prefs ) ) {
    if ( $src == 'post' ) {
      $prefix = substr ( $key, 0, 6 );
      $setting = substr ( $key, 6 );
      if ( $key == 'currenttab' )
        continue;
      // .
      // Validate key name.  Should start with "admin_" and not include
      // any unusual characters that might be an SQL injection attack.
      if ( ! preg_match ( '/admin_[A-Za-z0-9_]+$/', $key ) )
        die_miserable_death ( str_replace ( 'XXX', $key,
            translate ( 'Invalid setting name XXX.' ) ) );
    } else {
      $prefix = 'admin_';
      $setting = $key;
    }
    if ( strlen ( $setting ) > 0 && $prefix == 'admin_' ) {
      if ( $setting == 'THEME' && $value != 'none' )
        $my_theme = strtolower ( $value );

      $setting = strtoupper ( $setting );
      $sql = 'DELETE FROM webcal_config WHERE cal_setting = ?';
      if ( ! dbi_execute ( $sql, array ( $setting ) ) ) {
        $error = db_error ( false, $sql );
        break;
      }
      if ( strlen ( $value ) > 0 ) {
        $sql = 'INSERT INTO webcal_config ( cal_setting, cal_value ) VALUES ( ?, ? )';
        if ( ! dbi_execute ( $sql, array ( $setting, $value ) ) ) {
          $error = db_error ( false, $sql );
          break;
        }
      }
    }
  }
  // Reload preferences so any CSS changes will take effect.
  load_global_settings ();
  load_user_preferences ();
}

/* Generates HTML for color chooser options in admin pages.
 *
 * NOTE: This will be merged back into function print_color_input_html
 *       in includes/function.php when I remove the tables from pref.php.
 *
 * @param string $varname  the name of the variable to display
 * @param string $title    color description
 * @param string $varval   the default value to display
 *
 * @return string  HTML for the color selector.
 */
function admin_print_color_input_html ( $varname, $title, $varval = '' ) {
  global $prefarray, $s, $SCRIPT;
  static $select;

  $name = '';
  $setting = $varval;

  if ( empty ( $select ) )
    $select = translate ( 'Select' ) . '...';

  if ( $SCRIPT == 'admin.php' ) {
    $name = 'admin_';
    $setting = $s[$varname];
  } elseif ( $SCRIPT == 'pref.php' ) {
    $name = 'pref_';
    $setting = $prefarray[$varname];
  }

  $name .= $varname;

  return '
            <p><label for="' . $name . '">' . $title
   . ':</label><input type="text" name="' . $name . '" id="' . $name
   . '" size="7" maxlength="7" value="' . $setting
   . '" onchange="updateColor( this, \'' . $varname
   . '_sample\' );" /><span id="' . $varname . '_sample" style="background:'
   . $setting . ';">&nbsp;</span><input type="button" onclick="selectColor( \''
   . $name . '\', event )" value="' . $select . '" /></p>';
}

$currenttab = '';
$error = ( $is_admin ? '' : print_not_auth (3) );

if ( ! empty ( $_POST ) && empty ( $error ) ) {
  $currenttab = getPostValue ( 'currenttab' );
  $my_theme = '';

  save_pref ( $_POST, 'post' );

  if ( ! empty ( $my_theme ) ) {
    include_once 'themes/' . strtolower ( $my_theme ) . '.php';
    save_pref ( $webcal_theme, 'theme' );
  }
}
// .
// Load any new config settings.  Existing ones will not be affected.
// This function is in the install/default_config.php file.
if ( function_exists ( 'db_load_config' ) && empty ( $_POST ) )
  db_load_config ();

$menuthemes = $s = $themes = array ();

$res = dbi_execute ( 'SELECT cal_setting, cal_value FROM webcal_config' );

if ( $res ) {
  while ( $row = dbi_fetch_row ( $res ) ) {
    $setting = $row[0];
    $s[$setting] = $value = $row[1];
  }
  dbi_free_result ( $res );
}
// .
// Get list of theme files from /themes directory.
$dir = 'themes';
if ( is_dir ( $dir ) ) {
  if ( $dh = opendir ( $dir ) ) {
    while ( ( $file = readdir ( $dh ) ) !== false ) {
      if ( strpos ( $file, '_admin.php' ) ) {
        $themes[0][] = strtoupper ( str_replace ( '_admin.php', '', $file ) );
        $themes[1][] = strtoupper ( str_replace ( '.php', '', $file ) );
      } else
      if ( strpos ( $file, '_pref.php' ) ) {
        $themes[0][] = strtolower ( str_replace ( '_pref.php', '', $file ) );
        $themes[1][] = strtolower ( str_replace ( '.php', '', $file ) );
      }
    }
    sort ( $themes );
    closedir ( $dh );
  }
}
// .
// Get list of menu themes.
$dir = 'includes/menu/themes/';
if ( is_dir ( $dir ) ) {
  if ( $dh = opendir ( $dir ) ) {
    while ( ( $file = readdir ( $dh ) ) !== false ) {
      if ( $file == '.' || $file == '..' || $file == 'CVS' )
        continue;

      if ( is_dir ( $dir . $file ) )
        $menuthemes[] = $file;
    }
    closedir ( $dh );
  }
}

$currenttab = getPostValue ( 'currenttab', 'settings' );
$currenttab = ( ! empty ( $currenttab) ? $currenttab : 'settings' );

$BodyX = 'onload="init_admin();showTab( \'' . $currenttab . '\' );"';
print_header (
  array ( 'js/admin.php', 'js/visible.php' ), '', $BodyX );

if ( ! $error ) {
  // Make sure globals values passed to styles.php are for this user.
  // Makes the demo calendar and Page title accurate.
  $GLOBALS['APPLICATION_NAME'] = $s['APPLICATION_NAME'];
  $GLOBALS['BGCOLOR'] = $s['BGCOLOR'];
  $GLOBALS['CELLBG'] = $s['CELLBG'];
  $GLOBALS['FONTS'] = $s['FONTS'];
  $GLOBALS['H2COLOR'] = $s['H2COLOR'];
  $GLOBALS['HASEVENTSBG'] = $s['HASEVENTSBG'];
  $GLOBALS['MENU_THEME'] = $s['MENU_THEME'];
  $GLOBALS['MYEVENTS'] = $s['MYEVENTS'];
  $GLOBALS['OTHERMONTHBG'] = $s['OTHERMONTHBG'];
  $GLOBALS['TABLEBG'] = $s['TABLEBG'];
  $GLOBALS['TEXTCOLOR'] = $s['TEXTCOLOR'];
  $GLOBALS['THBG'] = $s['THBG'];
  $GLOBALS['THFG'] = $s['THFG'];
  $GLOBALS['TODAYCELLBG'] = $s['TODAYCELLBG'];
  $GLOBALS['WEEKENDBG'] = $s['WEEKENDBG'];
  $GLOBALS['WEEKNUMBER'] = $s['WEEKNUMBER'];

  define_languages (); // Load the language list.
  reset ( $languages );

  $checked = ' checked="checked"';
  $selected = ' selected="selected"';
  $select = translate ( 'Select' ) . '...';
  // .
  // Allow css_cache of webcal_config values.
  @session_start ();
  $_SESSION['webcal_tmp_login'] = 'blahblahblah';

  $editStr = '<input type="button" value="' . translate ( 'Edit' )
   . "...\" onclick=\"window.open( 'edit_template.php?type=%s','cal_template','"
   . 'dependent,menubar,scrollbars,height=500,width=500,outerHeight=520,'
   . 'outerWidth=520\' );" name="" />';
  $choices = array ( 'day.php', 'week.php', 'month.php', 'year.php' );
  $choices_text = array ( translate ( 'Day' ), translate ( 'Week' ),
    translate ( 'Month' ), translate ( 'Year' ) );

  $bottomStr = translate ( 'Bottom' );
  $topStr = translate ( 'Top' );

  $anyoneStr = translate ( 'Anyone' );
  $partyStr = translate ( 'Participant' );

  $saveStr = translate ( 'Save' );

  $option = '
                <option value="';
  $color_sets = $datestyle_md = $datestyle_my = $datestyle_tk = '';
  $datestyle_ymd = $lang_list = $menu_theme_list = $prefer_vu = '';
  $start_wk_on = $start_wkend_on = $tabs = $theme_list = $user_vu = '';
  $work_hr_end = $work_hr_start = '';
  // .
  // This should be easier to add more tabs if needed.
  $tabs_ar = array ( // .
    'settings', translate ( 'Settings' ),
    'public', translate ( 'Public Access' ),
    'uac', translate ( 'User Access Control' ),
    'groups', translate ( 'Groups' ),
    'nonuser', translate ( 'NonUser Calendars' ),
    'other', translate ( 'Other' ),
    'email', translate ( 'Email' ),
    'colors', translate ( 'Colors' )
    );
  for ( $i = 0, $cnt = count ( $tabs_ar ); $i < $cnt; $i++ ) {
    $tabs .= '
        <span class="tab' . ( $i > 0 ? 'bak' : 'for' ) . '" id="tab_'
     . $tabs_ar[$i] . '"><a href="" onclick="return setTab( \'' . $tabs_ar[$i]
     . '\' )">' . $tabs_ar[++$i] . '</a></span>';
  }
  // Move the loops here and combine a few.
  while ( list ( $key, $val ) = each ( $languages ) ) {
    $lang_list .= $option . $val . '"'
     . ( $val == $s['LANGUAGE'] ? $selected : '' )
     . '>' . $key . '</option>';
  }
  for ( $i = 0, $cnt = count ( $themes[0] ); $i < $cnt; $i++ ) {
    $theme_list .= $option . $themes[1][$i] . '">' . $themes[0][$i] . '</option>';
  }
  for ( $i = 0, $cnt = count ( $datestyles ); $i < $cnt; $i += 2 ) {
    $datestyle_ymd .= $option . $datestyles[$i] . '"'
     . ( $s['DATE_FORMAT'] == $datestyles[$i] ? $selected : '' )
     . '>' . $datestyles[$i + 1] . '</option>';
  }
  for ( $i = 0, $cnt = count ( $datestyles_my ); $i < $cnt; $i += 2 ) {
    $datestyle_my .= $option . $datestyles_my[$i] . '"'
     . ( $s['DATE_FORMAT_MY'] == $datestyles_my[$i] ? $selected : '' )
     . '>' . $datestyles_my[$i + 1] . '</option>';
  }
  for ( $i = 0, $cnt = count ( $datestyles_md ); $i < $cnt; $i += 2 ) {
    $datestyle_md .= $option . $datestyles_md[$i] . '"'
     . ( $s['DATE_FORMAT_MD'] == $datestyles_md[$i] ? $selected : '' )
     . '>' . $datestyles_md[$i + 1] . '</option>';
  }
  for ( $i = 0, $cnt = count ( $datestyles_task ); $i < $cnt; $i += 2 ) {
    $datestyle_tk .= $option . $datestyles_task[$i] . '"'
     . ( $s['DATE_FORMAT_TASK'] == $datestyles_task[$i] ? $selected : '' )
     . '>' . $datestyles_task[$i + 1] . '</option>';
  }
  for ( $i = 0; $i < 7; $i++ ) {
    $start_wk_on .= $option . "$i\""
     . ( $i == $s['WEEK_START'] ? $selected : '' )
     . '>' . weekday_name ( $i ) . '</option>';
    $j = ( $i == 0 ? 6 : $i - 1 ); // Make sure to start with Saturday.
    $start_wkend_on .= $option . "$j\""
     . ( $j == $s['WEEKEND_START'] ? $selected : '' )
     . '>' . weekday_name ( $j ) . '</option>';
  }
  for ( $i = 0; $i < 24; $i++ ) {
    $tmp = display_time ( $i * 10000, 1 );
    $work_hr_start .= $option . "$i\""
     . ( $i == $s['WORK_DAY_START_HOUR'] ? $selected : '' )
     . '>' . $tmp . '</option>';
    $work_hr_end .= $option . "$i\""
     . ( $i == $s['WORK_DAY_END_HOUR'] ? $selected : '' )
     . '>' . $tmp . '</option>';
  }
  for ( $i = 0, $cnt = count ( $choices ); $i < $cnt; $i++ ) {
    $prefer_vu .= $option . $choices[$i] . '"'
     . ( $s['STARTVIEW'] == $choices[$i] ? $selected : '' )
     . '>' . $choices_text[$i] . '</option>';
  }
  // Allow user to select a view also.
  for ( $i = 0, $cnt = count ( $views ); $i < $cnt; $i++ ) {
    if ( $views[$i]['cal_is_global'] != 'Y' )
      continue;

    $xurl = $views[$i]['url'];
    $xurl_strip = str_replace ( '&amp;', '&', $xurl );
    $user_vu .= $option . $xurl . '"'
     . ( $s['STARTVIEW'] == $xurl_strip ? $selected : '' )
     . '>' . $views[$i]['cal_name'] . '</option>';
  }
  foreach ( $menuthemes as $menutheme ) {
    $menu_theme_list .= $option . $menutheme . '"'
     . ( $s['MENU_THEME'] == $menutheme ? $selected : '' )
     . '>' . $menutheme . '</option>';
  }
  foreach ( array ( // Document color choices.
      'BGCOLOR' => translate ( 'Document background' ),
      'H2COLOR' => translate ( 'Document title' ),
      'TEXTCOLOR' => translate ( 'Document text' ),
      'MYEVENTS' => translate ( 'My event text' ),
      'TABLEBG' => translate ( 'Table grid color' ),
      'THBG' => translate ( 'Table header background' ),
      'THFG' => translate ( 'Table header text' ),
      'CELLBG' => translate ( 'Table cell background' ),
      'TODAYCELLBG' => translate ( 'Table cell background for current day' ),
      'HASEVENTSBG' => translate ( 'Table cell background for days with events' ),
      'WEEKENDBG' => translate ( 'Table cell background for weekends' ),
      'OTHERMONTHBG' => translate ( 'Table cell background for other month' ),
      'WEEKNUMBER' => translate ( 'Week number color' ),
      'POPUP_BG' => translate ( 'Event popup background' ),
      'POPUP_FG' => translate ( 'Event popup text' )
      ) as $k => $v ) {
    $color_sets .= admin_print_color_input_html ( $k, $v );
  }

  set_today ( date ( 'Ymd' ) );
  ob_start ();

  echo '
    <h2>' . translate ( 'System Settings' )
   . '<img src="images/help.gif" alt="' . translate ( 'Help' )
   . '" class="help" onclick="window.open( \'help_admin.php\', \'cal_help\', '
   . '\'dependent,menubar,scrollbars,height=400,width=400,innerHeight=420,'
   . 'outerWidth=420\' );" /></h2>
    <form action="admin.php" method="post" onsubmit="return valid_form( this );"'
   . ' name="prefform">'
   . display_admin_link () . '
      <input type="hidden" name="currenttab" id="currenttab" value="'
   . $currenttab . '" />
      <input type="submit" value="' . $saveStr
   . '" name="" /><br /><br />

<!-- TABS -->
      <div id="tabs">' . $tabs . '
      </div>

<!-- TABS BODY -->
      <div id="tabscontent">
<!-- DETAILS -->
        <div id="tabscontent_settings">
          <fieldset>
            <legend>' . translate ( 'System options' ) . '</legend>
            <p><label for="admin_APPLICATION_NAME" title="'
   . tooltip ( 'app-name-help' ) . '">' . translate ( 'Application Name' )
   . ':</label>
              <input type="text" size="40" name="admin_APPLICATION_NAME" '
   . 'id="admin_APPLICATION_NAME" value="'
   . htmlspecialchars ( $s['APPLICATION_NAME'] ) . '" />'
   . ( $s['APPLICATION_NAME'] == 'Title'
    /* translate ( 'Translated Name' ) */
    ? str_replace ( 'XXX', translate ( 'Title' ),
      translate ( 'Translated Name (XXX)' ) ) : '' ) . '</p>
            <p><label for="admin_SERVER_URL" title="'
   . tooltip ( 'server-url-help' ) . '">' . translate ( 'Server URL' )
   . ':</label>
              <input type="text" size="70" name="admin_SERVER_URL" '
   . 'id="admin_SERVER_URL" value="' . htmlspecialchars ( $s['SERVER_URL'] )
   . '" /></p>
            <p><label for="admin_HOME_LINK" title="'
   . tooltip ( 'home-url-help' ) . '">' . translate ( 'Home URL' ) . ':</label>
              <input type="text" size="40" name="admin_HOME_LINK" '
   . 'id="admin_HOME_LINK" value="'
   . ( empty ( $s['HOME_LINK'] ) ? '' : htmlspecialchars ( $s['HOME_LINK'] ) )
   . '" /></p>
            <p><label for="admin_LANGUAGE" title="' . tooltip ( 'language-help' )
   . '">' . translate ( 'Language' ) . ':</label>
              <select name="admin_LANGUAGE" id="admin_LANGUAGE">' . $lang_list . '
              </select>'/* translate ( 'Your browser default language is' ) */
   . str_replace ( 'XXX', translate ( get_browser_language ( true ) ),
    translate ( 'Your browser default language is XXX.' ) ) . '</p>
            <p><label>' . translate ( 'Allow user to use themes' ) . ':</label>'
   . print_radio ( 'ALLOW_USER_THEMES' ) . '</p>
            <p><label for="admin_THEME" title="' . tooltip ( 'themes-help' )
   . '">' . translate ( 'Themes' ) . ':</label>
              <select name="admin_THEME" id="admin_THEME">
                <option disabled="disabled">' . translate ( 'AVAILABLE THEMES' )
   . '</option>'
  /* Always use 'none' as default so we don't overwrite manual settings. */
   . $option . 'none"' . $selected . '>' . translate ( 'None' ) . '</option>'
   . $theme_list . '
              </select><input type="button" name="preview" value="'
   . translate ( 'Preview' ) . '" onclick="return showPreview()" />
            </p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Site customization' ) . '</legend>
            <p><label title="' . tooltip ( 'custom-script-help' ) . '">'
   . translate ( 'Custom script/stylesheet' ) . ':</label>'
   . print_radio ( 'CUSTOM_SCRIPT' );
  printf ( $editStr, 'S' );
  echo '</p>
            <p><label title="' . tooltip ( 'custom-header-help' ) . '">'
   . translate ( 'Custom header' ) . ':</label>'
   . print_radio ( 'CUSTOM_HEADER' );
  printf ( $editStr, 'H' );
  echo '</p>
            <p><label title="' . tooltip ( 'custom-trailer-help' ) . '">'
   . translate ( 'Custom trailer' ) . ':</label>'
   . print_radio ( 'CUSTOM_TRAILER' );
  printf ( $editStr, 'T' );
  echo '</p>
            <p><label title="' . tooltip ( 'enable-external-header-help' ) . '">'
   . translate ( 'Allow external file for header/script/trailer' ) . ':</label>'
   . print_radio ( 'ALLOW_EXTERNAL_HEADER' ) . '</p>
            <p><label>' . translate ( 'Allow user to override header/trailer' )
   . ':</label>' . print_radio ( 'ALLOW_USER_HEADER' ) . '</p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Date and Time' ) . '</legend>'
  /* Determine if we can set timezones.  If not don't display any options. */
   . ( set_env ( 'TZ', $s['SERVER_TIMEZONE'] ) ? '
            <p><label for="admin_SERVER_TIMEZONE" title="'
     . tooltip ( 'tz-help' ) . '">' . translate ( 'Server Timezone Selection' )
     . ':</label>' . print_timezone_select_html ( 'admin_', $s['SERVER_TIMEZONE'] )
     . '</p>' : '' ) . '
            <p><label title="' . tooltip ( 'display-general-use-gmt-help' )
   . '">' . translate ( 'Display Common Use Date/Times as GMT' ) . ':</label>'
   . print_radio ( 'GENERAL_USE_GMT' ) . '</p>
            <p><label title="' . tooltip ( 'date-format-help' ) . '">'
   . translate ( 'Date format' ) . ':</label>
              <select name="admin_DATE_FORMAT">' . $datestyle_ymd . '
              </select>' . $choices_text[2] . ' ' . $choices_text[0] . ' '
   . $choices_text[3] . '</p>
            <p><label>&nbsp;</label>
              <select name="admin_DATE_FORMAT_MY">' . $datestyle_my . '
              </select>' . $choices_text[2] . ' ' . $choices_text[3] . '</p>
            <p><label>&nbsp;</label>
              <select name="admin_DATE_FORMAT_MD">' . $datestyle_md . '
              </select>' . $choices_text[2] . ' ' . $choices_text[0] . '</p>
            <p><label>&nbsp;</label>
              <select name="admin_DATE_FORMAT_TASK">' . $datestyle_tk . '
              </select>' . translate ( 'Small Task Date' ) . '</p>
            <p><label title="' . tooltip ( 'display-week-starts-on' ) . '">'
   . translate ( 'Week starts on' ) . ':</label>
              <select name="admin_WEEK_START" id="admin_WEEK_START">'
   . $start_wk_on . '
              </select></p>
            <p><label title="' . tooltip ( 'display-weekend-starts-on' ) . '">'
   . translate ( 'Weekend starts on' ) . ':</label>
              <select name="admin_WEEKEND_START" id="admin_WEEKEND_START">'
   . $start_wkend_on . '
              </select></p>
            <p><label title="' . tooltip ( 'time-format-help' ) . '">'
   . translate ( 'Time format' ) . ':</label>' . print_radio ( 'TIME_FORMAT',
    array ( '12' => translate ( '12 hour' ), '24' => translate ( '24 hour' ) ) )
   . '</p>
            <p><label title="' . tooltip ( 'timed-evt-len-help' ) . '">'
   . translate ( 'Specify timed event length by' ) . ':</label>'
   . print_radio ( 'TIMED_EVT_LEN',
    array ( 'D' => translate ( 'Duration' ), 'E' => translate ( 'End Time' ) ) )
   . '</p>
            <p><label for="admin_WORK_DAY_START_HOUR" title="'
   . tooltip ( 'work-hours-help' ) . '">' . translate ( 'Work hours' )
   . ':</label>' . translate ( 'From' ) . '
              <select name="admin_WORK_DAY_START_HOUR" id="admin_WORK_DAY_START_HOUR">'
   . $work_hr_start . '
              </select>' . translate ( 'to' ) . '
              <select name="admin_WORK_DAY_END_HOUR" id="admin_WORK_DAY_END_HOUR">'
   . $work_hr_end . '
              </select></p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Appearance' ) . '</legend>
            <p><label for="admin_STARTVIEW" title="'
   . tooltip ( 'preferred-view-help' ) . '">' . translate ( 'Preferred view' )
   . ':</label>
              <select name="admin_STARTVIEW" id="admin_STARTVIEW">' . $prefer_vu
   . $user_vu . '
              </select></p>
            <p><label>' . translate ( 'Allow top menu' ) . ':</label>'
   . print_radio ( 'MENU_ENABLED' ) . '</p>
            <p><label>' . translate ( 'Date Selectors position' ) . ':</label>'
   . print_radio ( 'MENU_DATE_TOP', array ( 'Y' => $topStr, 'N' => $bottomStr ) )
   . '</p>
            <p><label for="admin_MENU_THEME" title="'
   . tooltip ( 'menu-themes-help' ) . '">' . translate ( 'Menu theme' )
   . ':</label>
              <select name="admin_MENU_THEME" id="admin_MENU_THEME">' . $option
   . 'none"' . $selected . '>' . translate ( 'None' ) . '</option>'
   . $menu_theme_list . '
              </select></p>
            <p><label for="admin_FONTS" title="' . tooltip ( 'fonts-help' )
   . '">' . translate ( 'Fonts' )
   . ':</label><input type="text" size="40" name="admin_FONTS" id="admin_FONTS" value="'
   . htmlspecialchars ( $s['FONTS'] ) . '" /></p>
            <p><label title="' . tooltip ( 'display-sm_month-help' ) . '">'
   . translate ( 'Display small months' ) . ':</label>'
   . print_radio ( 'DISPLAY_SM_MONTH' ) . '</p>
            <p><label title="' . tooltip ( 'display-weekends-help' ) . '">'
   . translate ( 'Display weekends' ) . ':</label>'
   . print_radio ( 'DISPLAY_WEEKENDS' ) . '</p>
            <p><label title="' . tooltip ( 'display-long-daynames-help' ) . '">'
   . translate ( 'Display long day names' ) . ':</label>'
   . print_radio ( 'DISPLAY_LONG_DAYS' ) . '</p>
            <p><label title="' . tooltip ( 'display-alldays-help' ) . '">'
   . translate ( 'Display all days in month view' ) . ':</label>'
   . print_radio ( 'DISPLAY_ALL_DAYS_IN_MONTH' ) . '</p>
            <p><label title="' . tooltip ( 'display-week-number-help' ) . '">'
   . translate ( 'Display week number' ) . ':</label>'
   . print_radio ( 'DISPLAY_WEEKNUMBER' ) . '</p>
            <p><label title="' . tooltip ( 'display-desc-print-day-help' ) . '">'
   . translate ( 'Display description in printer day view' ) . ':</label>'
   . print_radio ( 'DISPLAY_DESC_PRINT_DAY' ) . '</p>
            <p><label title="' . tooltip ( 'yearly-shows-events-help' ) . '">'
   . translate ( 'Display days with events in bold in month and year views' )
   . ':</label>' . print_radio ( 'BOLD_DAYS_IN_YEAR' ) . '</p>
            <p><label title="' . tooltip ( 'display-minutes-help' ) . '">'
   . translate ( 'Display 00 minutes always' ) . ':</label>'
   . print_radio ( 'DISPLAY_MINUTES' ) . '</p>
            <p><label title="' . tooltip ( 'display-end-times-help' ) . '">'
   . translate ( 'Display end times on calendars' ) . ':</label>'
   . print_radio ( 'DISPLAY_END_TIMES' ) . '</p>
            <p><label title="' . tooltip ( 'allow-view-add-help' ) . '">'
   . translate ( 'Include add event link in views' ) . ':</label>'
   . print_radio ( 'ADD_LINK_IN_VIEWS' ) . '</p>
            <p><label title="' . tooltip ( 'lunar-help' ) . '">'
   . translate ( 'Display Lunar Phases in month view' ) . ':</label>'
   . print_radio ( 'DISPLAY_MOON_PHASES' ) . '</p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Restrictions' ) . '</legend>
            <p><label title="' . tooltip ( 'allow-view-other-help' ) . '">'
   . translate ( 'Allow viewing other users calendars' ) . ':</label>'
   . print_radio ( 'ALLOW_VIEW_OTHER' ) . '</p>
            <p><label title="' . tooltip ( 'require-approvals-help' ) . '">'
   . translate ( 'Require event approvals' ) . ':</label>'
   . print_radio ( 'REQUIRE_APPROVALS' ) . '</p>
            <p><label title="' . tooltip ( 'display-unapproved-help' ) . '">'
   . translate ( 'Display unapproved' ) . ':</label>'
   . print_radio ( 'DISPLAY_UNAPPROVED' ) . '</p>
            <p><label title="' . tooltip ( 'conflict-check-help' ) . '">'
   . translate ( 'Check for event conflicts' ) . ':</label>'
  /* This control is logically reversed. */
   . print_radio ( 'ALLOW_CONFLICTS',
    array ( 'N' => translate ( 'Yes' ), 'Y' => translate ( 'No' ) ) ) . '</p>
            <p><label title="' . tooltip ( 'conflict-months-help' ) . '">'
   . translate ( 'Conflict checking months' ) . ':</label>
              <input type="text" size="3" '
   . 'name="admin_CONFLICT_REPEAT_MONTHS" value="'
   . htmlspecialchars ( $s['CONFLICT_REPEAT_MONTHS'] ) . '" /></p>
            <p><label title="' . tooltip ( 'conflict-check-override-help' )
   . '">' . translate ( 'Allow users to override conflicts' ) . ':</label>'
   . print_radio ( 'ALLOW_CONFLICT_OVERRIDE' ) . '</p>
            <p><label title="' . tooltip ( 'limit-appts-help' ) . '">'
   . translate ( 'Limit number of timed events per day' ) . ':</label>'
   . print_radio ( 'LIMIT_APPTS' ) . '</p>
            <p><label title="' . tooltip ( 'limit-appts-number-help' ) . '">'
   . translate ( 'Maximum timed events per day' ) . ':</label>
              <input type="text" size="3" name="admin_LIMIT_APPTS_NUMBER" value="'
   . htmlspecialchars ( $s['LIMIT_APPTS_NUMBER'] ) . '" /></p>
            <p><label title="' . tooltip ( 'crossday-help' ) . '">'
   . translate ( 'Disable Cross-Day Events' ) . ':</label>'
   . print_radio ( 'DISABLE_CROSSDAY_EVENTS' ) . '</p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Events' ) . '</legend>
            <p><label title="' . tooltip ( 'disable-location-field-help' ) . '">'
   . translate ( 'Disable Location field' ) . ':</label>'
   . print_radio ( 'DISABLE_LOCATION_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'disable-url-field-help' ) . '">'
   . translate ( 'Disable URL field' ) . ':</label>'
   . print_radio ( 'DISABLE_URL_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'disable-priority-field-help' ) . '">'
   . translate ( 'Disable Priority field' ) . ':</label>'
   . print_radio ( 'DISABLE_PRIORITY_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'disable-access-field-help' ) . '">'
   . translate ( 'Disable Access field' ) . ':</label>'
   . print_radio ( 'DISABLE_ACCESS_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'disable-participants-field-help' )
   . '">' . translate ( 'Disable Participants field' ) . ':</label>'
   . print_radio ( 'DISABLE_PARTICIPANTS_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'disable-repeating-field-help' )
   . '">' . translate ( 'Disable Repeating field' ) . ':</label>'
   . print_radio ( 'DISABLE_REPEATING_FIELD' ) . '</p>
            <p><label title="' . tooltip ( 'allow-html-description-help' )
   . '">' . translate ( 'Allow HTML in Description' ) . ':</label>'
   . print_radio ( 'ALLOW_HTML_DESCRIPTION' ) . '</p>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Popups' ) . '</legend>
            <p><label title="' . tooltip ( 'disable-popups-help' ) . '">'
   . translate ( 'Disable Pop-Ups' ) . ':</label>'
   . print_radio ( 'DISABLE_POPUPS', '', 'popup_handler' ) . '</p>
            <div id="pop">
              <p><label title="' . tooltip ( 'popup-includes-siteextras-help' )
   . '">' . translate ( 'Display Site Extras in popup' ) . ':</label>'
   . print_radio ( 'SITE_EXTRAS_IN_POPUP' ) . '</p>
              <p><label title="' . tooltip ( 'popup-includes-participants-help' )
   . '">' . translate ( 'Display Participants in popup' ) . ':</label>'
   . print_radio ( 'PARTICIPANTS_IN_POPUP' ) . '</p>
            </div>
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Miscellaneous' ) . '</legend>
            <p><label title="' . tooltip ( 'remember-last-login-help' ) . '">'
   . translate ( 'Remember last login' ) . ':</label>'
   . print_radio ( 'REMEMBER_LAST_LOGIN' ) . '</p>
            <p><label title="' . tooltip ( 'summary_length-help' ) . '">'
   . translate ( 'Brief Description Length' )
   . ':</label><input type="text" size="3" name="admin_SUMMARY_LENGTH" value="'
   . $s['SUMMARY_LENGTH'] . '" /></p>
            <p><label for="admin_USER_SORT_ORDER" title="'
   . tooltip ( 'user_sort-help' ) . '">' . translate ( 'User Sort Order' )
   . ':</label>
              <select name="admin_USER_SORT_ORDER" id="admin_USER_SORT_ORDER">'
   . $option . 'cal_lastname, cal_firstname" '
   . ( $s['USER_SORT_ORDER'] == 'cal_lastname, cal_firstname' ? $selected : '' )
   . '>' . translate ( 'Lastname, Firstname' ) . '</option>' . $option
   . 'cal_firstname, cal_lastname" '
   . ( $s['USER_SORT_ORDER'] == 'cal_firstname, cal_lastname' ? $selected : '' )
   . '>' . translate ( 'Firstname, Lastname' ) . '</option>
              </select></p>
          </fieldset>
        </div>
<!-- END SETTINGS -->

<!-- BEGIN PUBLIC ACCESS -->
        <div id="tabscontent_public">
          <p><label title=" ' . tooltip ( 'allow-public-access-help' ) . '">'
   . translate ( 'Allow public access' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS', '', 'public_handler' ) . '</p>
          <div id="pa">
            <p><label title="' . tooltip ( 'public-access-default-visible' )
   . '">' . translate ( 'Public access visible by default' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_DEFAULT_VISIBLE' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-default-selected' )
   . '">' . translate ( 'Public access is default participant' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_DEFAULT_SELECTED' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-view-others-help' )
   . '">' . translate ( 'Public access can view other users' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_OTHERS' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-can-add-help' ) . '">'
   . translate ( 'Public access can add events' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_CAN_ADD' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-add-requires-approval-help' )
   . '">' . translate ( 'Public access new events require approval' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_ADD_NEEDS_APPROVAL' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-sees-participants-help' )
   . '">' . translate ( 'Public access can view participants' ) . ':</label>'
   . print_radio ( 'PUBLIC_ACCESS_VIEW_PART' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-override-help' ) . '">'
   . translate ( 'Override event name/description for public access' )
   . ':</label>' . print_radio ( 'OVERRIDE_PUBLIC' ) . '</p>
            <p><label title="' . tooltip ( 'public-access-override-text-help' )
   . '">' . translate ( 'Text to display to public access' )
   . ':</label><input name="admin_OVERRIDE_PUBLIC_TEXT" value="'
   . $s['OVERRIDE_PUBLIC_TEXT'] . '" size="25" /></p>
            <p><label title="' . tooltip ( 'public-access-captcha-help' ) . '">'
   . translate ( 'Require CAPTCHA validation for public access new events' )
   . ':</label>' . print_radio ( 'ENABLE_CAPTCHA' ) . '</p>
           <div style="clear:both;"></div>
          </div>
        </div>

<!-- BEGIN USER ACCESS CONTROL -->
        <p id="tabscontent_uac"><label title="' . tooltip ( 'uac-enabled-help' )
   . '">' . translate ( 'User Access Control enabled' ) . ':</label>'
   . print_radio ( 'UAC_ENABLED' ) . '</p>

<!-- BEGIN GROUPS -->
        <div id="tabscontent_groups">
          <p><label title="' . tooltip ( 'groups-enabled-help' ) . '">'
   . translate ( 'Groups enabled' ) . ':</label>'
   . print_radio ( 'GROUPS_ENABLED' ) . '</p>
          <p><label title="' . tooltip ( 'user-sees-his-group-help' ) . '">'
   . translate ( 'User sees only his groups' ) . ':</label>'
   . print_radio ( 'USER_SEES_ONLY_HIS_GROUPS' ) . '</p>
        </div>

<!-- BEGIN NONUSER -->
        <div id="tabscontent_nonuser">
          <p><label title="' . tooltip ( 'nonuser-enabled-help' ) . '">'
   . translate ( 'Nonuser enabled' ) . ':</label>'
   . print_radio ( 'NONUSER_ENABLED' ) . '</p>
          <p><label title="' . tooltip ( 'nonuser-list-help' ) . '">'
   . translate ( 'Nonuser list' ) . ':</label>'
   . print_radio ( 'NONUSER_AT_TOP', array ( 'Y' => $topStr, 'N' => $bottomStr ) )
   . '</p>
        </div>

        <div id="tabscontent_other">
<!-- BEGIN UPCOMING EVENTS -->
   <fieldset><legend>' . translate('Upcoming Events') . '</legend>
   ' . htmlspecialchars ( $SERVER_URL ) . 'upcoming.php<br/>
   <p><label title="' . tooltip ( 'upcoming-events-help' ) . '">'
   . translate ( 'Enabled' ) . ':</label>'
   . print_radio ( 'UPCOMING_EVENTS', '', '', 'N' ) . '</p>

   <p><label title="' . tooltip ( 'upcoming-events-allow-override' ) .  '">'
   . translate ( 'Allow user override' ) . ':</label>'
   . print_radio ( 'UPCOMING_ALLOW_OVR', '', '', 'N' ) . '</p>

     <p><label title="' . tooltip ( 'upcoming-events-display-caticons' ) .  '">'
   . translate ( 'Display category icons' ) . ':</label>'
   . print_radio ( 'UPCOMING_DISPLAY_CAT_ICONS', '', '', 'Y' ) . '</p>

     <p><label title="' . tooltip ( 'upcoming-events-display-layers' ) .  '">'
   . translate ( 'Display layers' ) . ':</label>'
   . print_radio ( 'UPCOMING_DISPLAY_LAYERS', '', '', 'N' ) . '</p>

     <p><label title="' . tooltip ( 'upcoming-events-display-links' ) .  '">'
   . translate ( 'Display links to events' ) . ':</label>'
   . print_radio ( 'UPCOMING_DISPLAY_LINKS', '', '', 'Y' ) . '</p>

     <p><label title="' . tooltip ( 'upcoming-events-display-popups' ) .  '">'
   . translate ( 'Display event popups' ) . ':</label>'
   . print_radio ( 'UPCOMING_DISPLAY_POPUPS', '', '', 'Y' ) . '</p>
   </fieldset>

<!-- BEGIN REPORTS -->
          <p><label title="' . tooltip ( 'reports-enabled-help' ) . '">'
   . translate ( 'Reports enabled' ) . ':</label>'
   . print_radio ( 'REPORTS_ENABLED' ) . '</p>

<!-- BEGIN PUBLISHING -->
          <p><label title="' . tooltip ( 'subscriptions-enabled-help' ) . '">'
   . translate ( 'Allow remote subscriptions' ) . ':</label>'
   . print_radio ( 'PUBLISH_ENABLED' ) . '</p>'
  /* Determine if allow_url_fopen is enabled. */
   . ( preg_match ( '/(On|1|true|yes)/i', ini_get ( 'allow_url_fopen' ) ) ? '
          <p><label title="' . tooltip ( 'remotes-enabled-help' ) . '">'
     . translate ( 'Allow remote calendars' ) . ':</label>'
     . print_radio ( 'REMOTES_ENABLED' ) . '</p>' : '' ) . '
          <p><label title="' . tooltip ( 'rss-enabled-help' ) . '">'
   . translate ( 'Enable RSS feed' ) . ':</label>'
   . print_radio ( 'RSS_ENABLED' ) . '</p>

<!-- BEGIN CATEGORIES -->
          <p><label title="' . tooltip ( 'categories-enabled-help' ) . '">'
   . translate ( 'Categories enabled' ) . ':</label>'
   . print_radio ( 'CATEGORIES_ENABLED' ) . '</p>
          <p><label title="' . tooltip ( 'icon_upload-enabled-help' ) . '">'
   . translate ( 'Category Icon Upload enabled' ) . ':</label>'
   . print_radio ( 'ENABLE_ICON_UPLOADS' ) . '' . ( ! is_dir ( 'icons/' )
    /* translate ( 'Requires' ) translate ( 'folder to exist' ) */
    ? str_replace ( 'XXX', 'icons',
      translate ( '(Requires XXX folder to exist.)' ) ) : '' ) . '</p>

<!-- DISPLAY TASK PREFERENCES -->
          <p><label title="' . tooltip ( 'display-tasks-help' ) . '">'
   . translate ( 'Display small task list' ) . ':</label>'
   . print_radio ( 'DISPLAY_TASKS' ) . '</p>
          <p><label title="' . tooltip ( 'display-tasks-in-grid-help' ) . '">'
   . translate ( 'Display tasks in Calendars' ) . ':</label>'
   . print_radio ( 'DISPLAY_TASKS_IN_GRID' ) . '</p>

<!-- BEGIN EXT PARTICIPANTS -->
          <p><label title="' . tooltip ( 'allow-external-users-help' ) . '">'
   . translate ( 'Allow external users' ) . ':</label>'
   . print_radio ( 'ALLOW_EXTERNAL_USERS', '', 'eu_handler' ) . '</p>
          <div id="eu">
            <p><label title="' . tooltip ( 'external-can-receive-notification-help' )
   . '">' . translate ( 'External users can receive email notifications' )
   . ':</label>' . print_radio ( 'EXTERNAL_NOTIFICATIONS' ) . '</p>
            <p><label title="' . tooltip ( 'external-can-receive-reminder-help' )
   . '">' . translate ( 'External users can receive email reminders' )
   . ':</label>' . print_radio ( 'EXTERNAL_REMINDERS' ) . '</p>
          </div>

 <!-- BEGIN SELF REGISTRATION -->
          <p><label title="' . tooltip ( 'allow-self-registration-help' ) . '">'
   . translate ( 'Allow self-registration' ) . ':</label>'
   . print_radio ( 'ALLOW_SELF_REGISTRATION', '', 'sr_handler' ) . '</p>
          <div id="sr">
            <p><label title="' . tooltip ( 'use-blacklist-help' ) . '">'
   . translate ( 'Restrict self-registration to blacklist' ) . ':</label>'
   . print_radio ( 'SELF_REGISTRATION_BLACKLIST' ) . '</p>
            <p><label title="' . tooltip ( 'allow-self-registration-full-help' )
   . '">' . translate ( 'Use self-registration email notifications' )
   . ':</label>' . print_radio ( 'SELF_REGISTRATION_FULL' ) . '</p><br />
          </div>

<!-- TODO add account aging feature. -->

<!-- BEGIN ATTACHMENTS/COMMENTS -->
        <div><p><label title="' 
   . tooltip ( 'allow-attachment-help' ) . '">'
   . translate ( 'Allow file attachments to events' ) . ':</label>'
   . print_radio ( 'ALLOW_ATTACH', '', 'attach_handler' )
    . '</p><p id="at1" style="margin-left:25%"><strong>Note: </strong>'
   . translate ( 'Admin and owner can always add attachments if enabled.' )
   . '<br />' . print_checkbox ( array ( 'ALLOW_ATTACH_PART', 'Y', $partyStr ) )
   . print_checkbox ( array ( 'ALLOW_ATTACH_ANY', 'Y', $anyoneStr ) )
   . '</p><br/><p><label title="' 
   . tooltip ( 'allow-comments-help' ) . '">'
   . translate ( 'Allow comments to events' ) . ':</label>'
   . print_radio ( 'ALLOW_COMMENTS', '', 'comment_handler' )
   . '</p><p id="com1" style="margin-left:25%"><strong>Note: </strong>'
   . translate ( 'Admin and owner can always add comments if enabled.' )
   . '<br />' . print_checkbox ( array ( 'ALLOW_COMMENTS_PART', 'Y', $partyStr ) )
   . print_checkbox ( array ( 'ALLOW_COMMENTS_ANY', 'Y', $anyoneStr ) )
   . '</p><br /></div></div>

<!-- BEGIN EMAIL -->
        <div id="tabscontent_email">
          <p><label title="' . tooltip ( 'email-enabled-help' ) . '">'
   . translate ( 'Email enabled' ) . ':</label>'
   . print_radio ( 'SEND_EMAIL', '', 'email_handler' ) . '</p>
          <div id="em">
            <p><label title="' . tooltip ( 'email-default-sender' ) . '">'
   . translate ( 'Default sender address' )
   . ':</label><input type="text" size="30" name="admin_EMAIL_FALLBACK_FROM" value="'
   . htmlspecialchars ( $EMAIL_FALLBACK_FROM ) . '" /></p>
            <p><label title="' . tooltip ( 'email-mailer' ) . '">'
   . translate ( 'Email Mailer' ) . ':</label>
              <select name="admin_EMAIL_MAILER" onchange="email_handler()">'
   . $option . 'smtp" ' . ( $s['EMAIL_MAILER'] == 'smtp' ? $selected : '' )
   . '>SMTP</option>' . $option . 'mail" '
   . ( $s['EMAIL_MAILER'] == 'mail' ? $selected : '' ) . '>PHP mail</option>'
   . $option . 'sendmail" '
   . ( $s['EMAIL_MAILER'] == 'sendmail' ? $selected : '' ) . '>sendmail</option>
              </select></p>
            <div id="em_smtp">
              <p><label title="' . tooltip ( 'email-smtp-host' ) . '">'
   . translate ( 'SMTP Host name(s)' )
   . ':</label><input type="text" size="50" name="admin_SMTP_HOST" value="'
   . $s['SMTP_HOST'] . '" /></p>
              <p><label title="' . tooltip ( 'email-smtp-port' ) . '">'
   . translate ( 'SMTP Port Number' )
   . ':</label><input type="text" size="4" name="admin_SMTP_PORT" value="'
   . $s['SMTP_PORT'] . '" /></p>
              <p><label title="' . tooltip ( 'email-smtp-auth' ) . '">'
   . translate ( 'SMTP Authentication' ) . ':</label>'
   . print_radio ( 'SMTP_AUTH', '', 'email_handler' ) . '</p>
              <div id="em_auth">
                <p><label title="' . tooltip ( 'email-smtp-username' ) . '">'
   . translate ( 'SMTP Username' )
   . ':</label><input type="text" size="30" name="admin_SMTP_USERNAME" value="'
   . ( empty ( $s['SMTP_USERNAME'] ) ? '' : $s['SMTP_USERNAME'] ) . '" /></p>
                <p><label title="' . tooltip ( 'email-smtp-password' ) . '">'
   . translate ( 'SMTP Password' )
   . ':</label><input type="text" size="30" name="admin_SMTP_PASSWORD" value="'
   . ( empty ( $s['SMTP_PASSWORD'] ) ? '' : $s['SMTP_PASSWORD'] ) . '" /></p>
              </div>
            </div>
            <p class="bold">' . translate ( 'Default user settings' ) . ':</p>'
   . "<blockquote id=\"default-user-settings\">\n"
   . '<p><label title="' . tooltip ( 'email-format' ) . '">'
   . translate ( 'Email format preference' ) . ':</label>'
   . print_radio ( 'EMAIL_HTML',
     array ( 'Y'=> translate ( 'HTML' ),
             'N'=>translate ( 'Plain Text' ) )  ) . '</p>' 
   . '<p><label title="' . tooltip ( 'email-include-ics' ) . '">'
   . translate ( 'Include iCalendar attachments' ) . ':</label>'
   . print_radio ( 'EMAIL_ATTACH_ICS' ) . '</p>' 
   . '<p><label title="' . tooltip ( 'email-event-reminders-help' ) . '">'
   . translate ( 'Event reminders' ) . ':</label>'
   . print_radio ( 'EMAIL_REMINDER' ) . '</p>' 
   . '<p><label title="' . tooltip ( 'email-event-added' ) . '">'
   . translate ( 'Events added to my calendar' ) . ':</label>'
   . print_radio ( 'EMAIL_EVENT_ADDED' ) . '</p>
            <p><label title="' . tooltip ( 'email-event-updated' ) . '">'
   . translate ( 'Events updated on my calendar' ) . ':</label>'
   . print_radio ( 'EMAIL_EVENT_UPDATED' ) . '</p>
            <p><label title="' . tooltip ( 'email-event-deleted' ) . '">'
   . translate ( 'Events removed from my calendar' ) . ':</label>'
   . print_radio ( 'EMAIL_EVENT_DELETED' ) . '</p>
            <p><label title="' . tooltip ( 'email-event-rejected' ) . '">'
   . translate ( 'Event rejected by participant' ) . ':</label>'
   . print_radio ( 'EMAIL_EVENT_REJECTED' ) . '</p>
            <p><label title="' . tooltip ( 'email-event-create' ) . '">'
   . translate ( 'Event that I create' ) . ':</label>'
   . print_radio ( 'EMAIL_EVENT_CREATE' ) . '</p>
          </blockquote>
          </div>
        </div>

<!-- BEGIN COLORS -->
        <div id="tabscontent_colors">
          <fieldset>
            <legend>' . translate ( 'Color options' ) . '</legend>
<!-- BEGIN EXAMPLE MONTH -->
            <div style="float:right; width:45%; margin:0; background:'
   . $BGCOLOR . '">
              <p class="bold" style="text-align:center; color:' . $H2COLOR
   . ';">' . date_to_str ( date ( 'Ymd' ), $DATE_FORMAT_MY, false ) . '</p>'
   . display_month ( date ( 'm' ), date ( 'Y' ), true ) . '
            </div>
<!-- END EXAMPLE MONTH -->
            <p><label>' . translate ( 'Allow user to customize colors' )
   . ':</label>' . print_radio ( 'ALLOW_COLOR_CUSTOMIZATION' ) . '</p>
            <p><label title="' . tooltip ( 'gradient-colors' ) . '">'
   . translate ( 'Enable gradient images for background colors' ) . ':</label>'
   . ( function_exists ( 'imagepng' ) || function_exists ( 'imagegif' )
    ? print_radio ( 'ENABLE_GRADIENTS' ) : translate ( 'Not available' ) )
   . '</p><br />' . $color_sets . '
          </fieldset>
          <fieldset>
            <legend>' . translate ( 'Background Image options' ) . '</legend>
            <p><label for="admin_BGIMAGE" title="' . tooltip ( 'bgimage-help' )
   . '">' . translate ( 'Background Image' )
   . ':</label><input type="text" size="75" name="admin_BGIMAGE" id="admin_BGIMAGE" value="'
   . ( empty ( $s['BGIMAGE'] ) ? '' : htmlspecialchars ( $s['BGIMAGE'] ) ) . '" /></p>
            <p><label for="admin_BGREPEAT" title="' . tooltip ( 'bgrepeat-help' )
   . '">' . translate ( 'Background Repeat' )
   . ':</label><input type="text" size="30" name="admin_BGREPEAT" id="admin_BGREPEAT" value="'
   . ( empty ( $s['BGREPEAT'] ) ? '' : $s['BGREPEAT'] ) . '" /></p>
          </fieldset>
        </div>
      </div>
      <div style="clear:both;">
        <input type="submit" value="' . $saveStr . '" name="" />
      </div>
    </form>';
  ob_end_flush ();
} else // if $error
  echo print_error ( $error, true );
echo print_trailer ();

?>

Added adminhome.php.

























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
/* $Id: adminhome.php,v 1.40.2.1 2008/03/07 13:36:38 cknudsen Exp $

 Page Description:
  Serves as the home page for administrative functions.
 Input Parameters:
  None
 Security:
  Users will see different options available on this page.
 */
include_once 'includes/init.php';

define ( 'COLUMNS', 3 );

print_header ( '', '
    <style type="text/css">
      table.admin,
      .admin td a {
        background:' . $CELLBG . '
      }
      table.admin {
        border:1px solid #000;
        padding:5px
      }
      table.admin td {
        padding:20px
      }
      table.admin td,
      .admin td a {
        text-align:center
      }
      .admin td a {
        border:1px solid #EEE;
        border-color:#EEE #777 #777 #EEE;
        padding:10px
      }
      .admin td a:hover {
        border-color:#777 #EEE #EEE #777
        background:#AAA;
      }
    </style>
'
  );

$assistStr = translate ( 'Assistants' );
$prefStr = translate ( 'Preferences' );
$names = $links = array ();
/* Disabled for now...will move to menu when working properly
if ( $is_admin && ! empty ( $SERVER_URL ) &&
    access_can_access_function ( ACCESS_SYSTEM_SETTINGS ) ) {
  $names[] = translate ( 'Control Panel' );
  $links[] = 'controlpanel.php';
}
*/
if ( $is_nonuser_admin ) {
  if ( ! access_is_enabled () ||
      access_can_access_function ( ACCESS_PREFERENCES ) ) {
    $names[] = $prefStr;
    $links[] = 'pref.php?user=' . $user;
  }

  if ( $single_user != 'Y' ) {
    if ( ! access_is_enabled () ||
        access_can_access_function ( ACCESS_ASSISTANTS ) ) {
      $names[] = $assistStr;
      $links[] = 'assistant_edit.php?user=' . $user;
    }
  }
} else {
  if ( ( $is_admin && ! access_is_enabled () ) || ( access_is_enabled () &&
        access_can_access_function ( ACCESS_SYSTEM_SETTINGS ) ) ) {
    $names[] = translate ( 'System Settings' );
    $links[] = 'admin.php';
  }

  if ( ! access_is_enabled () ||
      access_can_access_function ( ACCESS_PREFERENCES ) ) {
    $names[] = $prefStr;
    $links[] = 'pref.php';
  }

  $names[] = ( $is_admin ? translate ( 'Users' ) : translate ( 'Account' ) );
  $links[] = 'users.php';

  if ( access_is_enabled () &&
      access_can_access_function ( ACCESS_ACCESS_MANAGEMENT ) ) {
    $names[] = translate ( 'User Access Control' );
    $links[] = 'access.php';
  }

  if ( $single_user != 'Y' ) {
    if ( ! access_is_enabled () ||
        access_can_access_function ( ACCESS_ASSISTANTS ) ) {
      $names[] = $assistStr;
      $links[] = 'assistant_edit.php';
    }
  }

  if ( $CATEGORIES_ENABLED == 'Y' ) {
    if ( ! access_is_enabled () ||
        access_can_access_function ( ACCESS_CATEGORY_MANAGEMENT ) ) {
      $names[] = translate ( 'Categories' );
      $links[] = 'category.php';
    }
  }

  if ( ! access_is_enabled () ||
      access_can_access_function ( ACCESS_VIEW_MANAGEMENT ) ) {
    $names[] = translate ( 'Views' );
    $links[] = 'views.php';
  }

  if ( ! access_is_enabled () ||
      access_can_access_function ( ACCESS_LAYERS ) ) {
    $names[] = translate ( 'Layers' );
    $links[] = 'layers.php';
  }

  if ( $REPORTS_ENABLED == 'Y' &&
    ( ! access_is_enabled () ||
        access_can_access_function ( ACCESS_REPORT ) ) ) {
    $names[] = translate ( 'Reports' );
    $links[] = 'report.php';
  }

  if ( $is_admin ) {
    $names[] = translate ( 'Delete Events' );
    $links[] = 'purge.php';
  }
  /*
 This Activity Log link shows ALL activity for ALL events, so you really need
 to be an admin user for this. Enabling "Activity Log" in UAC just gives you
 access to the log for your _own_ events or other events you have access to.
 */
  if ( $is_admin && ( ! access_is_enabled () ||
        access_can_access_function ( ACCESS_ACTIVITY_LOG ) ) ) {
    $names[] = translate ( 'Activity Log' );
    $links[] = 'activity_log.php';

    $names[] = translate ( 'System Log' );
    $links[] = 'activity_log.php?system=1';
  }

  if ( ( $is_admin || ! access_is_enabled () ) ||
    ( access_is_enabled && 
    access_can_access_function ( ACCESS_SECURITY_AUDIT ) ) ) {
    $names[] = translate ( 'Security Audit' );
    $links[] = 'security_audit.php';
  }

  if ( $is_admin && ! empty ( $PUBLIC_ACCESS ) && $PUBLIC_ACCESS == 'Y' ) {
    $names[] = translate ( 'Public Preferences' );
    $links[] = 'pref.php?public=1';
  }

  if ( $is_admin && ! empty ( $PUBLIC_ACCESS ) && $PUBLIC_ACCESS == 'Y' &&
    $PUBLIC_ACCESS_CAN_ADD == 'Y' && $PUBLIC_ACCESS_ADD_NEEDS_APPROVAL == 'Y' ) {
    $names[] = translate ( 'Unapproved Public Events' );
    $links[] = 'list_unapproved.php?user=__public__';
  }
}

echo '
    <h2>' . translate ( 'Administrative Tools' ) . '</h2>
    <table class="admin">';

for ( $i = 0, $cnt = count ( $names ); $i < $cnt; $i++ ) {
  echo ( $i % COLUMNS == 0 ? '
      <tr>' : '' ) . '
        <td>' . ( ! empty ( $links[$i] ) ? '<a href="' . $links[$i] . '">' : '' )
   . $names[$i] . ( ! empty ( $links[$i] ) ? '</a>' : '' ) . '</td>'
   . ( $i % COLUMNS == COLUMNS - 1 ? '
      </tr>' : '' );
}

if ( $i % COLUMNS != 0 ) {
  while ( $i % COLUMNS != 0 ) {
    echo '
        <td>&nbsp;</td>';
    $i++;
  }
}
echo '
      </tr>
    </table>
    ' . print_trailer ();

?>

Added ajax.php.































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?php
/* $Id: ajax.php,v 1.16.2.9 2012/03/03 01:54:14 cknudsen Exp $
 *
 * Description
 * This is the handler for Ajax httpXmlRequests.
 */
require_once 'includes/classes/WebCalendar.class';

$WebCalendar = new WebCalendar ( __FILE__ );

include 'includes/translate.php';
include 'includes/config.php';
include 'includes/dbi4php.php';
include 'includes/formvars.php';
include 'includes/functions.php';
require_valide_referring_url ();

$WebCalendar->initializeFirstPhase ();

include 'includes/' . $user_inc;
include 'includes/access.php';
include 'includes/validate.php';

$WebCalendar->initializeSecondPhase ();

load_global_settings ();
load_user_preferences ();
$WebCalendar->setLanguage ();

$cat_id = getValue ( 'cat_id', '-?[0-9,\-]*', true );
$name = getPostValue ( 'name' );
$page = getPostValue ( 'page' );

// We're processing edit_remotes Calendar ID field.
if ( $page == 'edit_remotes' || $page == 'edit_nonuser' ) {
  $res = dbi_execute ( 'SELECT cal_login FROM webcal_nonuser_cals
    WHERE cal_login = ?', array ( $NONUSER_PREFIX . $name ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    // Presuming we are using '_NUC_' as $NONUSER_PREFIX.
    if ( $name == substr ( $row[0], strlen ( $NONUSER_PREFIX ) ) )
      // translate ( 'Duplicate Name' )
      echo str_replace ( 'XXX', $name, translate ( 'Duplicate Name XXX', true ) );
  }
} elseif ( $page == 'register' || $page == 'edit_user' ) {
  // We're processing username field.
  $res = dbi_execute ( 'SELECT cal_login FROM webcal_user WHERE cal_login = ?',
    array ( $name ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    // translate ( 'Username already exists.' )
    if ( $row[0] == $name )
      echo str_replace ( 'XXX', $name,
        translate ( 'Username XXX already exists.', true ) );
  }
} elseif ( $page == 'email' ) {
  // We're processing email field from any page.
  $res = dbi_execute ( 'SELECT cal_email FROM webcal_user WHERE cal_email = ?',
    array ( $name ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    // translate ( 'Email address already exists.' )
    if ( $row[0] == $name )
      echo str_replace ( 'XXX', $name,
        translate ( 'Email address XXX already exists.', true ) );
  }
} elseif ( $page == 'minitask' ) {
  $name = ( ! empty ( $name ) ? $name : 0 );
  require_once 'includes/classes/Event.class';
  require_once 'includes/classes/RptEvent.class';
  include_once 'includes/gradient.php';
  $column_array = array ( 'we.cal_priority', 'we.cal_name',
    'we.cal_due_date', 'weu.cal_percent' );
  $task_filter = ' ORDER BY ' . $column_array[$name % 4]
   . ( $name > 3 ? ' ASC' : ' DESC' );
  echo display_small_tasks ( $cat_id );
}

?>

Added approve_entry.php.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
/* $Id: approve_entry.php,v 1.50.2.5 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();
require ( 'includes/classes/WebCalMailer.class' );

$error = '';

if ( $readonly == 'Y' )
  $error = print_not_auth (4);
// Give user a chance to add comments to approval email.
if ( getPostValue ( 'comments' ) != '' ) {
  $comments = getPostValue ( 'comments' );
  $cancel = getPostValue ( 'cancel' );
} else
if ( empty ( $ret ) ) {
  $q_string = ( ! empty ( $_SERVER['QUERY_STRING'] )
    ? '?' . $_SERVER['QUERY_STRING'] : '' );

  print_header ();
  echo '
    <form action="approve_entry.php' . $q_string
   . '" method="post" name="add_comments">
      <table border="0" cellspacing="5">
        <tr>
          <td align="center" valign="bottom"><h3>'
   . translate ( 'Additional Comments (optional)' ) . '</h3></td>
        <tr>
        <tr>
          <td align="center"><textarea name="comments" rows="5" '
   . 'cols="60"></textarea></td>
        </tr>
        <tr>
          <td align="center">
            <input type="submit" value="' . translate ( 'Approve and Send' )
   . '" />&nbsp;&nbsp;&nbsp;
            <input type="submit" value="' . translate ( 'Approve and Exit' )
   . '" />
          </td>
        </tr>
        <tr>
          <td>'
  . translate ( '(Your comments will be emailed to the event creator.)' ) . '</td>
        </tr>
      </table>
    </form>
  </body>
</html>
';
  exit;
}

$user = getValue ( 'user' );
$type = getValue ( 'type' );
$id = getValue ( 'id' );

// Allow administrators to approve public events.
$app_user = ( $PUBLIC_ACCESS == 'Y' && ! empty ( $public ) && $is_admin
  ? '__public__' : ( $is_assistant || $is_nonuser_admin ? $user : $login ) );
// If User Access Control is enabled, we check to see if they are
// allowed to approve for the specified user.
if ( access_is_enabled () && ! empty ( $user ) && $user != $login &&
    access_user_calendar ( 'approve', $user ) )
  $app_user = $user;

if ( empty ( $error ) && $id > 0 )
  update_status ( 'A', $app_user, $id, $type );

if ( ! empty ( $comments ) && empty ( $cancel ) ) {
  $mail = new WebCalMailer;
  // Email event creator to notify that it was approved with comments.
  // Get the name of the event.
  $res = dbi_execute ( 'SELECT cal_name, cal_description, cal_date, cal_time,
    cal_create_by FROM webcal_entry WHERE cal_id = ?', array ( $id ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    $name = $row[0];
    $description = $row[1];
    $fmtdate = $row[2];
    $time = sprintf ( "%06d", $row[3] );
    $creator = $row[4];
    dbi_free_result ( $res );
  }

  $eventstart = date_to_epoch ( $fmtdate . $time );
  // TODO figure out if creator wants approved comment email.
  // Check UAC.
  $send_user_mail = ( access_is_enabled ()
    ? access_user_calendar ( 'email', $creator, $login ) : 'Y' );

  $htmlmail = get_pref_setting ( $creator, 'EMAIL_HTML' );
  user_load_variables ( $creator, 'temp' );
  $user_TIMEZONE = get_pref_setting ( $creator, 'TIMEZONE' );
  set_env ( 'TZ', $user_TIMEZONE );
  $user_language = get_pref_setting ( $creator, 'LANGUAGE' );
  if ( $send_user_mail == 'Y' && strlen ( $tempemail ) && $SEND_EMAIL != 'N' ) {
    reset_language ( empty ( $user_language ) || ( $user_language == 'none' )
      ? $LANGUAGE : $user_language );

    // translate ( 'Hello' )
    $msg = str_replace ( 'XXX', $tempfullname, translate ( 'Hello, XXX.' ) )
    // translate ( 'An appointment has been approved and comments added by' )
    . "\n\n" . str_replace ( 'XXX', $login_fullname,
      translate ( 'XXX has approved an appointment and added comments.' ) ) . "\n\n"
    // translate ( 'The subject was' )
    . str_replace ( 'XXX', $name, translate ( 'Subject XXX' ) ) . "\n"
    // translate ( 'The description is' )
    . str_replace ( 'XXX', $description, translate ( 'Description XXX' ) ) . "\n"
    // translate ( 'Date' )
    . str_replace ( 'XXX', date_to_str ( $fmtdate ), translate ( 'Date XXX' ) )
    // translate ( 'Time' )
    . ' ' . ( empty ( $hour ) && empty ( $minute )
      ? '' : str_replace ( 'XXX',
        // Display using user's GMT offset and display TZID.
        display_time ( '', 2, $eventstart,
          get_pref_setting ( $creator, 'TIME_FORMAT' ) ),
        translate ( 'Time XXX' ) ) ) . "\n";

    if ( ! empty ( $SERVER_URL ) ) {
      // DON'T change & to &amp; here. email will handle it
      $url = $SERVER_URL . 'view_entry.php?id=' . $id . '&em=1';
      if ( $htmlmail == 'Y' )
        $url = activate_urls ( $url );

      $msg .= "\n" . $url;
    }
    if ( ! empty ( $comments ) )
      // translate ( 'Comments' )
      $msg .= "\n\n" . str_replace ( 'XXX', $comments,
        translate ( 'Comments XXX' ) );

    $from = ( strlen ( $login_email ) ? $login_email : $EMAIL_FALLBACK_FROM );
    // Send mail.
    $mail->WC_Send ( $login_fullname, $tempemail,
      $tempfullname, $name, $msg, $htmlmail, $from );
    activity_log ( $id, $login, $creator, LOG_NOTIFICATION,
      str_replace ( 'XXX', $app_user,
        translate ( 'Approved w/Comments by XXX.' ) ) );
  }
}
// Return to login TIMEZONE.
set_env ( 'TZ', $TIMEZONE );
if ( empty ( $error ) && empty ( $mailerError ) ) {
  do_redirect ( ! empty ( $ret ) && $ret == 'listall'
    ? 'list_unapproved.php'
    : ( ( ! empty ( $ret ) && $ret == 'list'
        ? 'list_unapproved.php?'
        : 'view_entry.php?id=' . $id . '&amp;' ) . 'user=' . $app_user ) );
  exit;
}
// Process errors.
$mail->MailError ( $mailerError, $error );

?>

Added assistant_edit.php.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<?php
/* $Id: assistant_edit.php,v 1.38 2007/07/28 19:21:57 bbannon Exp $ */
include_once 'includes/init.php';

if ( empty ( $login ) || $login == '__public__' ) {
  // Do not allow public access.
  do_redirect ( empty ( $STARTVIEW ) ? 'month.php' : "$STARTVIEW" );
  exit;
}

if ( $user != $login )
  $user = ( ( $is_admin || $is_nonuser_admin ) && $user ) ? $user : $login;

print_header ( ( $GROUPS_ENABLED == 'Y'
    ? array ( 'js/assistant_edit.php/true' ) : '' ) );

ob_start ();

echo '
    <form action="assistant_edit_handler.php" method="post" '
 . 'name="assistanteditform">' . ( $user ? '
      <input type="hidden" name="user" value="' . $user . '" />' : '' ) . '
      <h2>';

$assistStr = translate ( 'Assistants' );
if ( $is_nonuser_admin ) {
  nonuser_load_variables ( $user, 'nonuser' );
  echo $nonuserfullname . ' ' . $assistStr . '<br />
      -- ' . translate ( 'Admin mode' ) . ' --';
} else
  echo translate ( 'Your assistants' );

echo '</h2>
      ' . display_admin_link () . '
      <table>
        <tr>
          <td class="aligntop"><label for="users">'
 . $assistStr . ':</label></td>
          <td>
            <select name="users[]" id="users" size="10" multiple="multiple">';

// Get list of all users.
$users = get_my_users ();
// Get list of users for this view.
$res = dbi_execute ( 'SELECT cal_boss, cal_assistant FROM webcal_asst
   WHERE cal_boss = ?', array ( $user ) );

if ( $res ) {
  while ( $row = dbi_fetch_row ( $res ) ) {
    $assistantuser[$row[1]] = 1;
  }
  dbi_free_result ( $res );
}

for ( $i = 0, $cnt = count ( $users ); $i < $cnt; $i++ ) {
  $u = $users[$i]['cal_login'];
  if ( $u == $login || $u == '__public__' )
    continue;
  echo '
              <option value="' . $u . '"'
   . ( ! empty ( $assistantuser[$u] ) ? ' selected="selected"' : '' ) . '>'
   . $users[$i]['cal_fullname'] . '</option>';
}

echo '
            </select>' . ( $GROUPS_ENABLED == 'Y' ? '
            <input type="button" onclick="selectUsers()" value="'
   . translate ( 'Select' ) . '..." />' : '' ) . '
          </td>
        </tr>
        <tr>
          <td colspan="2" class="aligncenter"><br /><input type="submit" '
 . 'name="action" value="' . translate ( 'Save' ) . '" />
          </td>
        </tr>
      </table>
    </form>
    ';

ob_end_flush ();

echo print_trailer ();

?>

Added assistant_edit_handler.php.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
/* $Id: assistant_edit_handler.php,v 1.19.2.2 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();

$user = getPostValue ( 'user' );
$users = getPostValue ( 'users' );

$error = '';
if ( $user != $login )
  $user = ( ( $is_admin || $is_nonuser_admin ) && $user ) ? $user : $login;
# update user list
dbi_execute ( 'DELETE FROM webcal_asst WHERE cal_boss = ?', array ( $user ) );
if ( ! empty ( $users ) ) {
  for ( $i = 0, $cnt = count ( $users ); $i < $cnt; $i++ ) {
    dbi_execute ( 'INSERT INTO webcal_asst ( cal_boss, cal_assistant )
      VALUES ( ?, ? )', array ( $user, $users[$i] ) );
  }
}

echo error_check ( 'assistant_edit.php'
   . ( ( $is_admin || $is_nonuser_admin ) && $login != $user
    ? '?user=' . $user : '' ) );

?>

Added availability.php.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<?php
/* $Id: availability.php,v 1.24.2.3 2008/04/04 18:07:40 umcesrjones Exp $
 * Page Description:
 * Display a timebar view of a single day.
 *
 * Input Parameters:
 * month (*) - specify the starting month of the timebar
 * day (*)   - specify the starting day of the timebar
 * year (*)  - specify the starting year of the timebar
 * users (*) - csv of users to include
 * (*) required field
 *
 * Security:
 * Must have "allow view others" enabled ($ALLOW_VIEW_OTHER) in
 *   System Settings unless the user is an admin user ($is_admin).
 */

include_once 'includes/init.php';
// Don't allow users to use this feature if "allow view others" is disabled.
if ( $ALLOW_VIEW_OTHER == 'N' && ! $is_admin )
  // not allowed...
  exit;


$users = getGetValue ( 'users' );
$year = getGetValue ( 'year' );
$month = getGetValue ( 'month' );
$day = getGetValue ( 'day' );

// Input args in URL.
// users: list of comma-separated users.
// translate ( 'Program Error' ) translate ( 'No XXX specified!' )
$noXStr = translate ( 'Program Error No XXX specified!' );
if ( empty ( $users ) ) {
  echo str_replace ( 'XXX', translate ( 'user' ), $noXStr );
  exit;
} elseif ( empty ( $year ) ) {
  echo str_replace ( 'XXX', translate ( 'year' ), $noXStr );
  exit;
} elseif ( empty ( $month ) ) {
  echo str_replace ( 'XXX', translate ( 'month' ), $noXStr );
  exit;
} elseif ( empty ( $day ) ) {
  echo str_replace ( 'XXX', translate ( 'day' ), $noXStr );
  exit;
}

print_header (
  array ( 'js/availability.php/false/' . "$month/$day/$year/"
   . getGetValue ( 'form' ) ), '', 'onload="focus();"', true, false, true );

$next_url = $prev_url = '?users=' . $users;
$time = mktime ( 0, 0, 0, $month, $day, $year );
$date = date ( 'Ymd', $time );
$next_url .= strftime ( '&amp;year=%Y&amp;month=%m&amp;day=%d', $time + 86400 );
$prev_url .= strftime ( '&amp;year=%Y&amp;month=%m&amp;day=%d', $time - 86400 );
$span = ( $WORK_DAY_END_HOUR - $WORK_DAY_START_HOUR ) * 3 + 1;

$users = explode ( ',', $users );

$nextStr = translate ( 'Next' );
$prevStr = translate ( 'Previous' );

echo '
    <div style="width:99%;">
      <a title="' . $prevStr . '" class="prev" href="' . $prev_url
 . '"><img src="images/leftarrow.gif" class="prev" alt="'
 . $prevStr . '" /></a>
      <a title="' . $nextStr . '" class="next" href="' . $next_url
 . '"><img src="images/rightarrow.gif" class="next" alt="'
 . $nextStr . '" /></a>
      <div class="title">
        <span class="date">';
printf ( "%s, %s %d, %d", weekday_name ( strftime ( "%w", $time ) ),
  month_name ( $month - 1 ), $day, $year );
echo '</span><br />
      </div>
    </div><br />
    <form action="availability.php" method="post">
      ' . daily_matrix ( $date, $users ) . '
    </form>
    ' . print_trailer ( false, true, true );

?>

Added category.php.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php
/* $Id: category.php,v 1.45.2.4 2013/01/24 21:10:18 cknudsen Exp $ */

include_once 'includes/init.php';
// Load user and global cats.
load_user_categories ();

if ( $CATEGORIES_ENABLED == 'N' ) {
  send_to_preferred_view ();
  exit;
}

$catIcon = $catname = $error = $idStr = '';
$catIconStr = translate ( 'Category Icon' );
$globalStr = translate ( 'Global' );
$icon_path = 'icons/';
// If editing, make sure they are editing their own (or they are an admin user).
if ( ! empty ( $id ) ) {
  if ( empty ( $categories[$id] ) )
    $error =
    str_replace ( 'XXX', $id, translate ( 'Invalid entry id XXX.' ) );

  $catcolor = $categories[$id]['cat_color'];
  $catname = $categories[$id]['cat_name'];
  $catowner = $categories[$id]['cat_owner'];
  $catIcon = $icon_path . 'cat-' . $id . '.gif';
  $idStr = '<input name="id" type="hidden" value="' . $id . '" />';
} else
  $catcolor = '#000000';

$showIcon = ( ! empty ( $catIcon ) && file_exists ( $catIcon )
  ? 'visible' : 'hidden' );

print_header ( array ( 'js/visible.php' ) );

ob_start ();

echo '
    <h2>' . translate ( 'Categories' ) . '</h2>
    ' . display_admin_link ();

$add = getGetValue ( 'add' );
if ( empty ( $add ) )
  $add = 0;
// Adding/Editing category.
if ( ( ( $add == '1' ) || ( ! empty ( $id ) ) ) && empty ( $error ) ) {
  echo '
    <form action="category_handler.php" method="post" name="catform" '
   . 'enctype="multipart/form-data">' . $idStr . '
      <table cellspacing="2" cellpadding="3">
        <tr>
          <td width="25%"><label for="catname">' . translate ( 'Category Name' )
   . '</label></td>
          <td colspan="3"><input type="text" name="catname" size="20" value="'
   . htmlspecialchars ( $catname ) . '" /></td>
        </tr>' . ( $is_admin && empty ( $id ) ? '
        <tr>
          <td><label for="isglobal">' . $globalStr . ':</label></td>
          <td colspan="3">
            <label><input type="radio" name="isglobal" value="N" '
     . ( ! empty ( $catowner ) || empty ( $id ) ? ' checked = "checked"' : '' )
     . ' />&nbsp;' . translate ( 'No' ) . '</label>&nbsp;&nbsp;
            <label><input type="radio" name="isglobal" value="Y" '
     . ( empty ( $catowner ) && ! empty ( $id ) ? ' checked = "checked"' : '' )
     . ' />&nbsp;' . translate ( 'Yes' ) . '</label>
          </td>
        </tr>' : '' ) . '
        <tr>
          <td>'
   . print_color_input_html ( 'catcolor', translate ( 'Color' ), $catcolor )
   . '</td>
        </tr>
        <tr id="cat_icon" style="visibility: ' . $showIcon . '">
          <td><label>' . $catIconStr . ':</label></td>
          <td colspan="3"><img src="' . $catIcon
   . '" name="urlpic" id="urlpic" alt="' . $catIconStr . '" /></td>
        </tr>
        <tr id="remove_icon" style="visibility: ' . $showIcon . '">
          <td><label for="delIcon">' . translate ( 'Remove Icon' )
   . '</label></td>
          <td colspan="3"><input type="checkbox" name="delIcon" value="Y" /></td>
        </tr>
        <tr>
          <td colspan="4">
            <label for="FileName">' . ( is_dir ( $icon_path ) &&
    ( $ENABLE_ICON_UPLOADS == 'Y' || $is_admin )
    ? translate ( 'Add Icon to Category' ) . '</label><br />&nbsp;&nbsp;&nbsp;'
     . translate ( 'Upload' ) . '&nbsp;<span style="font-size:small;">'
     . translate ( 'gif 3kb max' ) . '</span>:
            <input type="file" name="FileName" id="fileupload" size="45" '
     . 'maxlength="50" value=""/>
          </td>
        </tr>
        </tr>
          <td colspan="4">
            <input type="hidden" name="urlname" size="50" />&nbsp;&nbsp;&nbsp;
            <input type="button" value="'
     . translate ( 'Search for existing icons' )
     . '" onclick="window.open( \'icons.php\', \'icons\',\''
     . 'dependent,menubar=no,scrollbars=n0,height=300,width=400,outerHeight=320'
     . ',outerWidth=420\' );" />
          </td>
        </tr>
        </tr>
          <td colspan="4">' : '' ) // end test of ENABLE_ICON_UPLOADS
  . '
            <input type="submit" name="action" value="'
   . ( $add == '1' ? translate ( 'Add' ) : translate ( 'Save' ) ) . '" />'
   . ( ! empty ( $id ) ? '
            <input type="submit" name="delete" value="'
     . translate ( 'Delete' ) . '" onclick="return confirm( '
     . str_replace ( 'XXX', translate ( 'entry', true ),
      translate ( 'Are you sure you want to delete this XXX?', true ) )
     . '\' )" />' : '' ) . '
          </td>
        </tr>
      </table>
    </form>';
} else
if ( empty ( $error ) ) {
  // Displaying Categories.
  $global_found = false;
  if ( ! empty ( $categories ) ) {
    echo '
    <ul>';
    foreach ( $categories as $K => $V ) {
      if ( $K < 1 )
        continue;
      $catIcon = $icon_path . 'cat-' . $K . '.gif';
      $catStr = '<span style="color: '
       . ( ! empty ( $V['cat_color'] ) ? $V['cat_color'] : '#000000' )
       . ';">' . htmlentities ( $V['cat_name'] ) . '</span>';
      echo '
      <li>' . ( $V['cat_owner'] == $login || $is_admin
        ? '<a href="category.php?id=' . $K . '">' . $catStr . '</a>' : $catStr );

      if ( empty ( $V['cat_owner'] ) ) {
        echo '<sup>*</sup>';
        $global_found = true;
      }

      echo ( file_exists ( $catIcon ) ? '<img src="' . $catIcon . '" alt="'
         . $catIconStr . '" title="' . $catIconStr . '" />' : '' ) . '</li>';
    }
    echo '
    </ul>';
  }
  echo ( $global_found ? '<br /><br />
    <sup>*</sup> ' . $globalStr : '' ) . '
    <p><a href="category.php?add=1">' . translate ( 'Make New Category' )
   . '</a></p><br />';
}
ob_end_flush ();
echo ( ! empty ( $error ) ? print_error ( $error ) : '' ) . print_trailer ();

?>

Added category_handler.php.



















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
/* $Id: category_handler.php,v 1.33.2.7 2013/01/24 21:10:18 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();

$icon_max_size = '3000';
$icon_path = 'icons/';

/* Rename any icons associated with this cat_id. */
function renameIcon ( $id ) {
  global $icon_path;
  $bakIcon = $catIcon = $icon_path . 'cat-';
  $bakIcon .= date ( 'YmdHis' ) . '.gif';
  $catIcon .= $id . '.gif';
  if ( file_exists ( $catIcon ) )
    rename ( $catIcon, $bakIcon );
}

// Does the category belong to the user?
$is_my_event = false;
$id = getValue ( 'id' );
$catname = getValue ( 'catname' );
// prohibit any html in category name (including <script>)
$catname = strip_tags ( $catname );
$catcolor = getValue ( 'catcolor' );
$isglobal = getValue ( 'isglobal' );
$delIcon = getPostValue ( 'delIcon' );
if ( empty ( $id ) )
  $is_my_event = true; // New event.
else {
  $res = dbi_execute ( 'SELECT cat_id, cat_owner FROM webcal_categories
    WHERE cat_id = ?', array ( $id ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );

    $is_my_event = ( $row[0] == $id && $row[1] == $login ||
      ( empty ( $row[1] ) && $is_admin ) );

    dbi_free_result ( $res );
  } else
    $error = db_error ();
}

if ( ! empty ( $_FILES['FileName'] ) )
  $file = $_FILES['FileName'];

// Make sure we clear $file if no file was upoaded.
if ( ! empty ( $file['tmp_name'] ) && $file['tmp_name'] == 'none' )
  $file = '';

if ( ! $is_my_event )
  $error = print_not_auth (5);

$delete = getPostValue ( 'delete' );
if ( empty ( $error ) && ! empty ( $delete ) ) {
  // Delete this category.
  if ( ! dbi_execute ( 'DELETE FROM webcal_categories
    WHERE cat_id = ? AND ( cat_owner = ?'
       . ( $is_admin ? ' OR cat_owner IS NULL )' : ' )' ),
        array ( $id, $login ) ) ) {
    $error = db_error ();
  }

  if ( ! dbi_execute ( 'DELETE FROM webcal_entry_categories
    WHERE cat_id = ? AND ( cat_owner = ?'
       . ( $is_admin ? ' OR cat_owner IS NULL )' : ' )' ),
        array ( $id, $login ) ) ) {
    $error = db_error ();
  }
  // Rename any icons associated with this cat_id.
  renameIcon ( $id );
} else if ( empty ( $error ) && empty ( $catname ) ) {
  $error = translate ( 'Category name is required' );
} else if ( empty ( $error ) ) {
  if ( ! empty ( $id ) ) {
    # Update (don't let them change global status).
    if ( ! dbi_execute ( 'UPDATE webcal_categories
      SET cat_name = ?, cat_color = ? WHERE cat_id = ?',
        array ( $catname, $catcolor, $id ) ) )
      $error = db_error ();

    if ( ! empty ( $delIcon ) && $delIcon == 'Y' )
      renameIcon ( $id );
  } else {
    // Add new category.
    // Get new id.
    $res = dbi_execute ( 'SELECT MAX( cat_id ) FROM webcal_categories' );
    if ( $res ) {
      $row = dbi_fetch_row ( $res );
      $id = $row[0] + 1;
      dbi_free_result ( $res );
      $catowner = ( $is_admin
        ? ( $isglobal == 'Y' ? null : $login )
        : $login );

      if ( ! dbi_execute ( 'INSERT INTO webcal_categories ( cat_id, cat_owner,
        cat_name, cat_color ) VALUES ( ?, ?, ?, ? )',
          array ( $id, $catowner, $catname, $catcolor ) ) )
        $error = db_error ();
    } else
      $error = db_error ();
  }
  if ( empty ( $delIcon ) && is_dir( $icon_path ) && ( !
        empty ( $ENABLE_ICON_UPLOADS ) && $ENABLE_ICON_UPLOADS == 'Y' ||
        $is_admin ) ) {
    // Save icon if uploaded.
    if ( ! empty ( $file['tmp_name'] ) ) {
      if ( $file['type'] == 'image/gif' && $file['size'] <= $icon_max_size ) {
        // $icon_props = getimagesize ( $file['tmp_name']  );
        // print_r ($icon_props );
        $path_parts = pathinfo ( $_SERVER['SCRIPT_FILENAME'] );
        $fullIcon = $path_parts['dirname'] . '/'
         . $icon_path . 'cat-' . $id . '.gif';
        renameIcon ( $id );
        $file_result = move_uploaded_file ( $file['tmp_name'], $fullIcon );
        // echo "Upload Result:" . $file_result;
      } else
      if ( $file['size'] > $icon_max_size )
        $error = translate ( 'File size exceeds maximum.' );
      else
      if ( $file['type'] != 'image/gif' )
        $error = translate ( 'File is not a gif image.' );
    }
    // Copy icon if local file specified.
    $urlname = getPostvalue ( 'urlname' );
    if ( ! empty ( $urlname ) && file_exists ( $icon_path . $urlname ) )
      copy ( $icon_path . $urlname, $icon_path . 'cat-' . $id . '.gif' );
  }
}

if ( empty ( $error ) )
  do_redirect ( 'category.php' );

print_header ();
echo print_error ( $error ) . print_trailer ();

?>

Added catsel.php.



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
/* $Id: catsel.php,v 1.22.2.4 2013/01/24 21:10:19 cknudsen Exp $ */
include_once 'includes/init.php';

// load user and global cats
load_user_categories ();

$catList = $catNames = $error = '';

if ( $CATEGORIES_ENABLED == 'N' )
  exit;

$cats = getGetValue ( 'cats' );
$form = getGetValue ( 'form' );

$eventcats = explode ( ',', $cats );

$availCatStr = translate ( 'AVAILABLE CATEGORIES' );
$availCatFiller = str_repeat( '&nbsp;', ( 30 - strlen ( $availCatStr ) ) / 2 );
if ( strlen ( $availCatStr ) < 30 )
  $availCatStr = $availCatFiller . $availCatStr . $availCatFiller ;

$entryCatStr = translate ( 'ENTRY CATEGORIES' );
$entryCatFiller = str_repeat( '&nbsp;', ( 30 - strlen ( $entryCatStr ) ) / 2 );
if ( strlen ( $entryCatStr ) < 30 )
  $entryCatStr = $entryCatFiller . $entryCatStr . $entryCatFiller ;

print_header ( array ( 'js/catsel.php/false/' . $form ),
  '', '', true, false, true );

ob_start ();

echo '
    <table align="center" border="0" width="90%">
      <tr>
        <th colspan="3">' . translate ( 'Categories' ) . '</th>
      </tr>
      <form action="" method="post" name="editCategories" '
 . 'onSubmit="sendCats( this )">
      <tr>
        <td valign="top">';

if ( ! empty ( $categories ) ) {
  echo '
          <select name="cats[]" size="10">
            <option disabled>' . $availCatStr . '</option>';

  foreach ( $categories as $K => $V ) {
    // None is index -1 and needs to be ignored
    if ( $K > 0 && ( $V['cat_owner'] == $login || $is_admin ||
        substr ( $form, 0, 4 ) == 'edit' ) ) {
      $tmpStr = $K .
        '" name="' . htmlentities ( $V['cat_name'] ) .
        '">' . htmlentities ( $V['cat_name'] );
      echo '
            <option value="' . ( empty ( $V['cat_owner'] )
        ? "-$tmpStr" . '<sup>*</sup>' : $tmpStr ) . '</option>';
    }
  }
  echo '
          </select>';
}
echo '
        </td>
        <td valign="center"><input type="button" value=">>" onclick="selAdd()"'
 . ' /></td>
        <td align="center" valign="top">
          <select name="eventcats[]" size="9" multiple>
            <option disabled>' . $entryCatStr . '</option>';

if ( strlen ( $cats ) ) {
  foreach ( $eventcats as $K ) {
    // disable if not creator and category is Global
    $show_ast = '';
    $disabled = ( empty ( $categories[abs ( $K )]['cat_owner'] ) &&
      substr ( $form, 0, 4 ) != 'edit' ? 'disabled' : '' );
    if ( empty ( $categories[abs ( $K )]['cat_owner'] ) ) {
      $show_ast = '*';
    }
    echo '
            <option value="' . "$K\" $disabled>"
     . htmlentities ( $categories[abs ( $K )]['cat_name'] ) . $show_ast . '</option>';
  }
}

ob_end_flush ();

echo '
          </select>
          <input type="button" value="' . translate ( 'Remove' )
 . '" onclick="selRemove()" />
        </td>
      </tr>
      <tr>
        <td valign="top" align="right">*' . translate ( 'Global Category' )
 . '&nbsp;&nbsp;&nbsp;<input type="button" value="' . translate ( 'OK' )
 . '" onclick="sendCats()" /></td>
        <td colspan="2" align="left">&nbsp;&nbsp;<input type="button" value="'
 . translate ( 'Cancel' ) . '" onclick="window.close()" /></td>
      </tr>
      </form>
    </table>
    ' . print_trailer ( false, true, true );

?>

Added colors.php.

















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
/* $Id: colors.php,v 1.33.2.2 2007/08/06 02:28:29 cknudsen Exp $ */
include_once 'includes/init.php';
$color = getGetValue ( 'color' );
if ( empty ( $color ) )
  exit;

$addcustomStr = translate ( 'Add Custom' );
$basicStr = translate ( 'Basic Colors' );
$cancelStr = translate ( 'Cancel' );
$currentStr = translate ( 'Current Color' );
$customStr = translate ( 'Custom Colors' );
$oldStr = translate ( 'Old Color' );
$okStr = '&nbsp;&nbsp;&nbsp;' . translate ( 'OK' ). '&nbsp;&nbsp;&nbsp;';
print_header ( array ( 'js/colors.php/true' ), '',
  'onload="fillhtml(); setInit();"', true, false, true );

/*
  HTML Color Editor v1.2 (c) 2000 by Sebastian Weber <webersebastian@yahoo.de>
  Modified by Ray Jones for inclusion into WebCalendar.
  NOTE: In-line CSS styles must remain in this file for proper operation
*/

echo <<<EOT
    <form action="colors.php" name="colorpicker">
      <input type="hidden" id="colorcell" value="{$color}" />
      <table cellspacing="2" cellpadding="0" align="center">
        <tr>
          <td colspan="3">
            <img height="1" src="images/blank.gif" border="0" alt="" /></td>
        </tr>
        <tr>
          <td align="center">{$basicStr}</td>
<!-- COLORS PICTURE -->
          <td rowspan="5" width="220" align="center">
            <img id="colorpic" height="192" width="192" src="images/colors.jpg"
              onclick="setFromImage(event);" alt="" /></td>
<!-- ***** SLIDER **** -->
          <td rowspan="5">
            <table cellspacing="0" cellpadding="0" width="24"
              onclick="setFromSlider(event);">
              <tr>
                <td id="slider"></td>
              </tr>
            </table>
          </td>
        </tr>
        <tr>
<!--  BASIC COLORS PALETTE  -->
          <td align="center" id="colorchoices"></td>
        </tr>
        <tr>
          <td align="center">{$customStr}</td>
        </tr>
        <tr>
<!--  Custom Colors  -->
          <td align="center" id="colorcustom"></td>
        </tr>
        <tr>
          <td align="center"><input type="button" value="{$addcustomStr}"
            onclick="definePreColor()" /></td>
        </tr>
        <tr>
          <td valign="top" colspan="3">
            <table cellpadding="2" cellspacing="0" width="100%">
              <tr align="center">
                <td colspan="2" height="30" valign="bottom">{$currentStr}</td>
                <td valign="bottom">{$oldStr}</td>
              </tr>
              <tr>
<!-- RGB INPUT -->
                <td class="boxtop boxleft boxbottom" valign="top" align="right">
                  R: <input id="rgb_r" type="text" size="3" maxlength="3"
                    value="255" onchange="setFromRGB()" /><br />
                  G: <input id="rgb_g" type="text" size="3" maxlength="3"
                    value="255" onchange="setFromRGB()" /><br />
                  B: <input id="rgb_b" type="text" size="3" maxlength="3"
                    value="255" onchange="setFromRGB()" /><br />
                  HTML: <input id="htmlcolor" type="text" size="6" maxlength="6"
                    value="FFFFFF" onchange="setFromHTML()" />
                </td>
                <td class="boxtop boxright boxbottom" width="120">
          <table id="thecell" bgcolor="#ffffff" align="center"
border="1" cellspacing="0" cellpadding="0">
                    <tr>
                      <td><img src="images/blank.gif" width="55" height="53" border="0" alt="" /></td>
                    </tr>
                  </table>
                </td>
                <td valign="middle" align="center" class="boxtop boxright
                  boxbottom">
<!--  Display New Color  -->
        <table id="theoldcell" bgcolor="#ffffff" border="1" cellspacing="0" cellpadding="0">
                    <tr>
            <td><img src="images/blank.gif" width="55" height="53" border="0" alt="" /></td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td colspan="3" align="center" height="30">
            <input type="button"
              value="&nbsp;&nbsp;&nbsp;{$okStr}&nbsp;&nbsp;&nbsp;"
              onclick="transferColor(); window.close()"
              />&nbsp;&nbsp;&nbsp;<input type="button"
              value="{$cancelStr}" onclick="window.close()" />
          </td>
        </tr>
      </table>
    </form>
<img id="cross" src="images/cross.gif" alt="" style="position:absolute; left:0px; top:0px" />
<img id="sliderarrow" src="images/arrow.gif" alt="" style="position:absolute; left:0px; top:0px" />
  </body>
</html>
EOT;

?>

Added controlpanel.php.



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
/* $Id: controlpanel.php,v 1.12.2.4 2011/04/27 00:27:35 rjones6061 Exp $
 *
 * Description:
 * This page generates the JNLP contents
 * that Java Web Start uses to start the application.
 *
 * For more info on Java Web Start:
 *  http://www.java.com/en/download/faq/5000070700.xml
 *
 * This starts up the us.k5n.webcalendar.ui.ControlPanel.Main application.
 * The ControlPanel application may eventually take over as the
 * primary way of administering parts of WebCalendar.
 *
 * Security:
 * This page doesn't really need securing since it just passes info to the
 * web start app. The web start app then does its own authenticating since
 * the web services require authentication to do anything.
 *
 **************************************************************************/

require_once 'includes/classes/WebCalendar.class';
require_once 'includes/classes/Event.class';
require_once 'includes/classes/RptEvent.class';

$WebCalendar = new WebCalendar ( __FILE__ );

include 'includes/translate.php';
include 'includes/config.php';
include 'includes/dbi4php.php';
include 'includes/formvars.php';
include 'includes/functions.php';

$WebCalendar->initializeFirstPhase ();

include 'includes/' . $user_inc;

$WebCalendar->initializeSecondPhase ();

load_global_settings ();

$WebCalendar->setLanguage ();

// Set content type for java web start
header ( "Content-type: application/x-java-jnlp-file" );

// Make sure app name is set
$appStr = generate_application_name ();

echo '<?xml version="1.0" encoding="utf-8"?>
<jnlp
  spec="1.0+"
  codebase="' . $SERVER_URL . '"
  href="controlpanel.php">
  <information>
    <title>' . translate ( 'Control Panel' ) . ': ' . htmlentities ( $appStr );

?></title>
    <vendor>k5n.us</vendor>
    <homepage href="http://www.k5n.us"/>
    <description>WebCalendar Control Panel</description>
    <!-- <icon href="images/xxx.gif"/> -->
  </information>
  <security>
  </security>
  <resources>
    <j2se version="1.4+"/>
    <jar href="ws/webcalendar.jar"/>
  </resources>
  <application-desc main-class="us.k5n.webcalendar.ui.ControlPanel.Main"
   width="600" height="500">
    <argument>-url=<?php echo $SERVER_URL . '</argument>'
 . ( $use_http_auth
  ? '
    <argument>-httpusername=' . $login . '</argument>'
  : ( ! empty ( $login ) ? '
    <argument>-user=' . $login . '</argument>' : '' ) )

?>
  </application-desc>
</jnlp>

Added css_cacher.php.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
/* $Id: css_cacher.php,v 1.18.2.2 2007/11/13 19:37:28 umcesrjones Exp $ */
define ( '_ISVALID', true );

include 'includes/translate.php';
include 'includes/config.php';
include 'includes/dbi4php.php';
include 'includes/formvars.php';
include 'includes/functions.php';

do_config ( 'includes/settings.php' );
include 'includes/' . $user_inc;
include_once 'includes/access.php';
include_once 'includes/validate.php';
include_once 'includes/gradient.php';

load_global_settings ();

@session_start ();
$login = ( empty ( $_SESSION['webcal_login'] )
  ? '__public__' : $_SESSION['webcal_login'] );
$login = ( empty ( $_SESSION['webcal_tmp_login'] )
  ? $login : $_SESSION['webcal_tmp_login'] );
// .
// If calling script uses 'guest', we must also.
if ( ! empty ( $_GET['login'] ) )
  $login = $_GET['login'];
else
if ( ! empty ( $_REQUEST['login'] ) )
  $login = $_REQUEST['login'];

if ( substr ( $login, 0, 10 ) == '__public__' )
  $login = '__public__';
	
load_user_preferences ( $login );
// .
// We will cache CSS as default, but override from admin and pref
// by incrementing the webcalendar_csscache cookie value.
$cookie = ( isset ( $_COOKIE['webcalendar_csscache'] )
  ? $_COOKIE['webcalendar_csscache'] : 0 );

header ( 'Content-type: text/css' );
header ( 'Last-Modified: ' . date ( 'r', mktime ( 0, 0, 0 ) + $cookie ) );
// .
// If we are calling from admin or pref, expire CSS now.
if ( empty ( $_SESSION['webcal_tmp_login'] ) ) {
  header ( 'Expires: ' . date ( 'D, j M Y H:i:s', time () + 86400 ) . ' UTC' );
  header ( 'Cache-Control: Public' );
  header ( 'Pragma: Public' );
}

if ( ini_get ( 'zlib.output_compression' ) != 1 )
  ob_start( 'ob_gzhandler' );

include_once ( 'includes/styles.php' );

unset ( $_SESSION['webcal_tmp_login'] );

?>

Added datesel.php.









































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
/* $Id: datesel.php,v 1.54.2.2 2007/08/06 02:28:29 cknudsen Exp $ */
include_once 'includes/init.php';

$fday = getGetValue ( 'fday' );
$fmonth = getGetValue ( 'fmonth' );
$fyear = getGetValue ( 'fyear' );

$form = getGetValue ( 'form' );
$date = getGetValue ( 'date' );

if ( strlen ( $date ) > 0 ) {
  $thisyear = substr ( $date, 0, 4 );
  $thismonth = substr ( $date, 4, 2 );
} else {
  $thisyear = date ( 'Y' );
  $thismonth = date ( 'm' );
}

$href = 'href="datesel.php?form=' . $form . '&amp;fday=' . $fday
 . '&amp;fmonth=' . $fmonth . '&amp;fyear=' . $fyear . '&amp;date=';

$nextdate = $href . date ( 'Ym01"', mktime ( 0, 0, 0, $thismonth + 1, 1, $thisyear ) );
$nextStr = translate ( 'Next' );

$prevdate = $href . date ( 'Ym01"', mktime ( 0, 0, 0, $thismonth - 1, 1, $thisyear ));
$previousStr = translate ( 'Previous' );

$monthStr = month_name ( $thismonth - 1 );

$wkstart = get_weekday_before ( $thisyear, $thismonth );

$monthstartYmd = date ( 'Ymd', mktime ( 0, 0, 0, $thismonth, 1, $thisyear ) );
$monthendYmd = date ( 'Ymd', mktime ( 23, 59, 59, $thismonth + 1, 0, $thisyear ) );

print_header ( '','', '', true, false, true, true, true );

//build weekday names
$wkdys = '';
for ( $i = 0; $i < 7; $i++ ) {
  $wkdys .= '<td>' . weekday_name ( ( $i + $WEEK_START ) % 7, 'D' ) . '</td>';
}
//build month grid
$mdays = '';
for ( $i = $wkstart; date ( 'Ymd', $i ) <= $monthendYmd; $i += 604800 ) {
  $mdays .= '
             <tr>';
  for ( $j = 0; $j < 7; $j++ ) {
    $date = $i + ( $j * 86400 ) + 43200;
    $dateYmd = date ( 'Ymd', $date );
    $mdays .= '
               <td'
     . ( ( $dateYmd >= $monthstartYmd && $dateYmd <= $monthendYmd ) ||
      $DISPLAY_ALL_DAYS_IN_MONTH == 'Y'
      ? ' class="field"><a href="javascript:sendDate(\''
       . $dateYmd . '\')">' . date ( 'j', $date ) . '</a>'
      : '>' ) . '</td>';
  }
  $mdays .= '
             </tr>';
}

$mdays .= '
             </table>
            </td>
          </tr>
      </table>
    </div>
    ';

echo <<<EOT
    <div align="center">
      <table class="aligncenter" width="100%">
        <tr>
          <td align="center" valign="top">
            <table class="aligncenter" cellpadding="3" cellspacing="2">
              <tr>
                <td><a title="{$previousStr}" class="prev" {$prevdate}>
                  <img src="images/leftarrowsmall.gif"
                     alt="{$previousStr}" /></a></td>
                <th colspan="5">&nbsp;{$monthStr}&nbsp;{$thisyear}&nbsp;</th>
                <td><a title="{$nextStr}"class="next" {$nextdate}>
                  <img src="images/rightarrowsmall.gif"
                     alt="{$nextStr}" /></a></td>
              </tr>
              <tr class="day">
               {$wkdys}
              </tr>
              {$mdays}

  <!--we'll leave this javascript here to speed things up-->
  <script language="javascript" type="text/javascript">
  <!-- <![CDATA[
  function sendDate ( date ) {
    year = date.substring ( 0, 4 );
    month = date.substring ( 4, 6 );
    day = date.substring ( 6, 8 );
    sday = window.opener.document.{$form}.{$fday};
    smonth = window.opener.document.{$form}.{$fmonth};
    syear = window.opener.document.{$form}.{$fyear};
    sday.selectedIndex = day - 1;
    smonth.selectedIndex = month - 1;
    for ( i = 0; i < syear.length; i++ ) {
      if ( syear.options[i].value == year ) {
        syear.selectedIndex = i;
      }
    }
    window.close ();
  }
  //]]> -->
  </script>
EOT;

echo print_trailer ( false, true, true );

?>

Added day.php.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
/* $Id: day.php,v 1.78.2.4 2008/03/31 21:03:41 umcesrjones Exp $ */
include_once 'includes/init.php';

//check UAC
if ( ! access_can_access_function ( ACCESS_DAY ) || 
  ( ! empty ( $user ) && ! access_user_calendar ( 'view', $user ) )  )
  send_to_preferred_view ();
  
load_user_layers ( $user != $login && $is_nonuser_admin ? $user : '' );

load_user_categories ();

$wday = strftime ( '%w', mktime ( 0, 0, 0, $thismonth, $thisday, $thisyear ) );
$now = mktime ( 23, 59, 59, $thismonth, $thisday, $thisyear );
$nowYmd = date ( 'Ymd', $now );

$next = mktime ( 0, 0, 0, $thismonth, $thisday + 1, $thisyear );
$nextday = date ( 'd', $next );
$nextmonth = date ( 'm', $next );
$nextyear = date ( 'Y', $next );
$nextYmd = date ( 'Ymd', $next );

$prev = mktime ( 0, 0, 0, $thismonth, $thisday - 1, $thisyear );
$prevday = date ( 'd', $prev );
$prevmonth = date ( 'm', $prev );
$prevyear = date ( 'Y', $prev );
$prevYmd = date ( 'Ymd', $prev );

if ( empty ( $TIME_SLOTS ) )
  $TIME_SLOTS = 24;

$boldDays = ( $BOLD_DAYS_IN_YEAR == 'Y' );

$startdate = mktime ( 0, 0, 0, $thismonth, 0, $thisyear );
$enddate = mktime ( 23, 59, 59, $thismonth + 1, 0, $thisyear );

$printerStr = $unapprovedStr = '';

/* Pre-Load the repeated events for quckier access */
$repeated_events = read_repeated_events ( empty ( $user )
  ? $login : $user, $startdate, $enddate, $cat_id );

/* Pre-load the non-repeating events for quicker access */
$events = read_events ( empty ( $user )
  ? $login : $user, $startdate, $enddate, $cat_id );

if ( empty ( $DISPLAY_TASKS_IN_GRID ) || $DISPLAY_TASKS_IN_GRID == 'Y' )
  /* Pre-load tasks for quicker access */
  $tasks = read_tasks ( ! empty ( $user ) && strlen ( $user ) && $is_assistant
    ? $user : $login, $now, $cat_id );

$smallTasks = ( $DISPLAY_TASKS == 'Y' ? '<div id="minitask">
           ' . display_small_tasks ( $cat_id ) . '
          </div>' : '' );
$dayStr = print_day_at_a_glance ( $nowYmd, ( empty ( $user )
    ? $login : $user ), $can_add );
$navStr = display_navigation ( 'day' );
$smallMonthStr = display_small_month ( $thismonth, $thisyear, true );
if ( empty ( $friendly ) ) {
  $unapprovedStr = display_unapproved_events (
    $is_assistant || $is_nonuser_admin ? $user : $login );
  $printerStr = generate_printer_friendly ( 'day.php' );
}
$eventinfo = ( empty ( $eventinfo ) ? '' : $eventinfo );
$trailerStr = print_trailer ();
print_header ( array ( 'js/popups.php/true' ), generate_refresh_meta (), '',
  false, false, false, false );

echo <<<EOT

    <table width="100%" cellpadding="1">
      <tr>
        <td width="80%">
          {$navStr}
        </td>
        <td class="aligntop" rowspan="2">
          <!-- START MINICAL -->
          <div class="minicalcontainer">
            {$smallMonthStr}
          </div>
          {$smallTasks}
        </td>
      </tr>
      <tr>
        <td>
          {$dayStr}
        </td>
      </tr>
    </table>
    {$eventinfo}
    {$unapprovedStr}
    {$printerStr}
    {$trailerStr}
EOT;

?>

Added del_entry.php.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
<?php
/* $Id: del_entry.php,v 1.75.2.5 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require ( 'includes/classes/WebCalMailer.class' );
$mail = new WebCalMailer;

require_valide_referring_url ();

$can_edit = $my_event = false;
$other_user = '';

// First, check to see if this user should be able to delete this event.
if ( $id > 0 ) {
  // Then see who has access to edit this entry.
  $can_edit = ( $is_admin || $readonly != 'Y' );

  // If assistant is doing this, then we need to switch login to user in the SQL.
  $query_params = array ();
  $query_params[] = $id;
  $sql = 'SELECT we.cal_id, we.cal_type FROM webcal_entry we,
    webcal_entry_user weu WHERE we.cal_id = weu.cal_id AND we.cal_id = ? ';
  if ( ! $is_admin ) {
    $sql .= ' AND ( we.cal_create_by = ? OR weu.cal_login = ? )';
    $sqlparm = ( $is_assistant ? $user : $login );
    $query_params[] = $sqlparm;
    $query_params[] = $sqlparm;
  }
  $res = dbi_execute ( $sql, $query_params );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    if ( $row && $row[0] > 0 )
      $can_edit = true;

    $activity_type = $row[1];
    dbi_free_result ( $res );
  }
}
if ( strpos ( 'EM', $activity_type ) !== false ) {
  $log_delete = LOG_DELETE;
  $log_reject = LOG_REJECT;
} else {
  $log_delete = LOG_DELETE_T;
  $log_reject = LOG_REJECT_T;
}
// See who owns the event. Owner should be able to delete.
$res = dbi_execute ( 'SELECT cal_create_by FROM webcal_entry WHERE cal_id = ?',
  array ( $id ) );
if ( $res ) {
  $row = dbi_fetch_row ( $res );
  $owner = $row[0];
  dbi_free_result ( $res );

  if ( $owner == $login || $is_assistant && $user == $owner || $is_nonuser_admin )
    $can_edit = $my_event = true;

  // Check UAC.
  if ( access_is_enabled () && ! $is_admin )
    $can_edit = access_user_calendar ( 'edit', $owner );
}

// If the user is the event creator or their assistant
// allow them to delete the event from another user's calendar.
// It's essentially the same thing as editing the event and removing the
// user from the participants list.
if ( $my_event && ! empty ( $user ) && $user != $login && ! $is_assistant )
  $other_user = $user;

if ( $readonly == 'Y' )
  $can_edit = false;

// If User Access Control is enabled, check to see if the current
// user is allowed to delete events from the other user's calendar.
if ( ! $can_edit && access_is_enabled () && ! empty ( $user ) &&
    access_user_calendar ( 'edit', $user ) )
  $can_edit = true;

if ( ! $can_edit )
  $error = print_not_auth (6);

// Is this a repeating event?
$event_repeats = false;
$res = dbi_execute ( 'SELECT COUNT( cal_id ) FROM webcal_entry_repeats
  WHERE cal_id = ?', array ( $id ) );
if ( $res ) {
  $row = dbi_fetch_row ( $res );
  if ( $row[0] > 0 )
    $event_repeats = true;

  dbi_free_result ( $res );
}
$override_repeat = false;
if ( ! empty ( $date ) && $event_repeats && ! empty ( $override ) )
  $override_repeat = true;

if ( $id > 0 && empty ( $error ) ) {
  if ( ! empty ( $date ) )
    $thisdate = $date;
  else {
    $res = dbi_execute ( 'SELECT cal_date FROM webcal_entry WHERE cal_id = ?',
      array ( $id ) );
    if ( $res ) {
      // date format is 19991231
      $row = dbi_fetch_row ( $res );
      $thisdate = $row[0];
    }
  }

  // Only allow delete of webcal_entry & webcal_entry_repeats
  // if owner or admin, not participant.
  // If a user was specified, then only delete that user (not here) even if we
  // are the owner or an admin.
  if ( ( $is_admin || $my_event ) && ! $other_user ) {
    // Email participants that the event was deleted.
    // First, get list of participants (with status Approved or Waiting on approval).
    $res = dbi_execute ( 'SELECT cal_login FROM webcal_entry_user
      WHERE cal_id = ? AND cal_status IN ( \'A\', \'W\' )', array ( $id ) );
    $partlogin = array ();
    if ( $res ) {
      while ( $row = dbi_fetch_row ( $res ) ) {
        $partlogin[] = $row[0];
      }
      dbi_free_result ( $res );
    }
    // Get event name.
    $res = dbi_execute ( 'SELECT cal_name, cal_date, cal_time FROM webcal_entry
      WHERE cal_id = ?', array ( $id ) );
    if ( $res ) {
      $row = dbi_fetch_row ( $res );
      $name = $row[0];
      $fmtdate = $row[1];
      $time = sprintf ( "%06d", $row[2] );
      dbi_free_result ( $res );
    }

    $eventstart = date_to_epoch ( $fmtdate . $time );
    $TIME_FORMAT = 24;
    for ( $i = 0, $cnt = count ( $partlogin ); $i < $cnt; $i++ ) {
      // Log the deletion.
      activity_log ( $id, $login, $partlogin[$i], $log_delete, '' );
      // Check UAC.
      $can_email = ( access_is_enabled ()
        ? access_user_calendar ( 'email', $partlogin[$i], $login ) : false );

      // Don't email the logged in user.
      if ( $can_email && $partlogin[$i] != $login ) {
        set_env ( 'TZ', get_pref_setting ( $partlogin[$i], 'TIMEZONE' ) );
        $user_language = get_pref_setting ( $partlogin[$i], 'LANGUAGE' );
        user_load_variables ( $partlogin[$i], 'temp' );
        if ( ! $is_nonuser_admin && $partlogin[$i] != $login &&
          get_pref_setting ( $partlogin[$i], 'EMAIL_EVENT_DELETED' ) == 'Y' &&
            boss_must_be_notified ( $login, $partlogin[$i] ) && !
            empty ( $tempemail ) && $SEND_EMAIL != 'N' ) {
          reset_language ( empty ( $user_language ) || $user_language == 'none'
            ? $LANGUAGE : $user_language );
          // Use WebCalMailer class.
          $mail->WC_Send ( $login_fullname, $tempemail, $tempfullname, $name,
            str_replace ( 'XXX', $tempfullname, translate ( 'Hello, XXX.' ) )
             . ".\n\n" . str_replace ( 'XXX', $login_fullname,
              // translate ( 'An appointment has been canceled for you by' )
              translate ( 'XXX has canceled an appointment.' ) ) . "\n"
             . str_replace ( 'XXX', $name, translate ( 'Subject XXX' ) ) . "\"\n"
             . str_replace ( 'XXX', date_to_str ( $thisdate ),
              translate ( 'Date XXX' ) ) . "\n"
             . ( ! empty ( $eventtime ) && $eventtime != '-1'
              ? str_replace ( 'XXX', display_time ( '', 2, $eventstart,
                  get_pref_setting ( $partlogin[$i], 'TIME_FORMAT' ) ),
                translate ( 'Time XXX' ) ) : '' ) . "\n\n",
            // Apply user's GMT offset and display their TZID.
            get_pref_setting ( $partlogin[$i], 'EMAIL_HTML' ), $login_email );
        }
      }
    }

    // Instead of deleting from the database...
    // mark it as deleted by setting the status for each participant to "D"
    // (instead of "A"/Accepted, "W"/Waiting-on-approval or "R"/Rejected).
    if ( $override_repeat ) {
      dbi_execute ( 'INSERT INTO webcal_entry_repeats_not
        ( cal_id, cal_date, cal_exdate ) VALUES ( ?, ?, ? )',
        array ( $id, $date, 1 ) );
      // Should we log this to the activity log???
    } else {
      // If it's a repeating event, delete any event exceptions that were entered.
      if ( $event_repeats ) {
        $res = dbi_execute ( 'SELECT cal_id FROM webcal_entry WHERE cal_group_id = ?',
          array ( $id ) );
        if ( $res ) {
          $ex_events = array ();
          while ( $row = dbi_fetch_row ( $res ) ) {
            $ex_events[] = $row[0];
          }
          dbi_free_result ( $res );
          for ( $i = 0, $cnt = count ( $ex_events ); $i < $cnt; $i++ ) {
            $res = dbi_execute ( 'SELECT cal_login FROM
              webcal_entry_user WHERE cal_id = ?', array ( $ex_events[$i] ) );
            if ( $res ) {
              $delusers = array ();
              while ( $row = dbi_fetch_row ( $res ) ) {
                $delusers[] = $row[0];
              }
              dbi_free_result ( $res );
              for ( $j = 0, $cnt = count ( $delusers ); $j < $cnt; $j++ ) {
                // Log the deletion.
                activity_log ( $ex_events[$i], $login, $delusers[$j],
                  $log_delete, '' );
                dbi_execute ( 'UPDATE webcal_entry_user SET cal_status = ?
                  WHERE cal_id = ? AND cal_login = ?',
                  array ( 'D', $ex_events[$i], $delusers[$j] ) );
              }
            }
          }
        }
      }

      // Now, mark event as deleted for all users.
      dbi_execute ( 'UPDATE webcal_entry_user SET cal_status = \'D\' WHERE cal_id = ?',
        array ( $id ) );

      // Delete External users for this event
      dbi_execute ( 'DELETE FROM webcal_entry_ext_user WHERE cal_id = ?',
        array ( $id ) );
    }
  } else {
    // Not the owner of the event, but participant or noncal_admin.
    // Just  set the status to 'D' instead of deleting.
    $del_user = ( ! empty ( $other_user ) ? $other_user : $login );
    if ( ! empty ( $user ) && $user != $login ) {
      if ( $is_admin || $my_event || ( $can_edit && $is_assistant ) ||
          ( access_is_enabled () &&
            access_user_calendar ( 'edit', $user ) ) ) {
        $del_user = $user;
      } else
        // Error: user cannot delete from other user's calendar.
        $error = print_not_auth (6);
    }
    if ( empty ( $error ) ) {
      if ( $override_repeat ) {
        dbi_execute ( 'INSERT INTO webcal_entry_repeats_not
          ( cal_id, cal_date, cal_exdate ) VALUES ( ?, ?, ? )',
          array ( $id, $date, 1 ) );
        // Should we log this to the activity log???
      } else {
        dbi_execute ( 'UPDATE webcal_entry_user SET cal_status = ?
          WHERE cal_id = ? AND cal_login = ?', array ( 'D', $id, $del_user ) );
        activity_log ( $id, $login, $login, $log_reject, '' );
      }
    }
  }
}

$ret = getValue ( 'ret' );
$return_view = get_last_view ();

if ( ! empty ( $ret ) ) {
  if ( $ret == 'listall' )
    $url = 'list_unapproved.php';
  else
  if ( $ret == 'list' )
    $url = 'list_unapproved.php' . ( empty ( $user ) ? '' : '?user=' . $user );
} else
if ( ! empty ( $return_view ) )
  do_redirect ( $return_view );
else
  $url = get_preferred_view ( '', empty ( $user ) ? '' : 'user=' . $user );

// Return to login TIMEZONE.
set_env ( 'TZ', $TIMEZONE );
if ( empty ( $error ) && empty ( $mailerError ) ) {
  do_redirect ( $url );
  exit;
}
// Process errors.
$mail->MailError ( $mailerError, $error );

?>

Added del_layer.php.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
/* $Id: del_layer.php,v 1.20.2.2 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';

require_valide_referring_url ();

$id = getGetValue ( 'id' );

if ( $ALLOW_VIEW_OTHER != 'Y' || empty ( $id ) ) {
  print_header ();
  echo print_not_auth (7) . print_trailer ();
  exit;
}
$id = getGetValue ( 'id' );
$updating_public = false;
if ( $is_admin && ! empty ( $public ) && $PUBLIC_ACCESS == 'Y' ) {
  $updating_public = true;
  $layer_user = '__public__';
} else
  $layer_user = $login;

load_user_layers ( $layer_user, 1 );

if ( strlen ( $layers[$id]['cal_layeruser'] ) > 0 &&
    ( $is_admin || $readonly == 'N' ) ) {
  $layeruser = $layers[$id]['cal_layeruser'];

  dbi_execute ( 'DELETE FROM webcal_user_layers WHERE cal_login = ?
    AND cal_layeruser = ?', array ( $layer_user, $layeruser ) );
}

  do_redirect ( 'layers.php' . ( $updating_public ? '?public=1' : '' ) );

?>

Added doc.php.































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?php
/* $Id: doc.php,v 1.20.2.4 2011/04/27 00:27:35 rjones6061 Exp $
 *
 * Description:
 *  Obtain a binary object from the database and send it back to
 *  the browser using the correct mime type.
 *
 * Input Parameters:
 *  blid(*) - The unique identifier for this blob
 * (*) required field
 */
include_once 'includes/init.php';
include_once 'includes/classes/Doc.class';

$blid = getValue ( 'blid', '-?[0-9]+', true );
$error = $res = '';
$invalidIDStr = translate ( 'Invalid entry id XXX.' );

if ( empty ( $blid ) )
  $error = translate ( 'Invalid blob id' );
else {
  $res = dbi_execute ( Doc::getSQLForDocId ( $blid ) );
  if ( ! $res )
   $error = db_error ();
}

if ( empty ( $error ) ) {
  $row = dbi_fetch_row ( $res );
  if ( ! $row )
    $error = str_replace ( 'XXX', $blid, $invalidIDStr );
  else {
    $doc = new Doc ( $row );
    $description = $doc->getDescription ();
    $filedata = $doc->getData ();
    $filename = $doc->getName ();
    $id = $doc->getId ();
    $mimetype = $doc->getMimeType ();
    $owner = $doc->getLogin ();
    $size = $doc->getSize ();
    $type = $doc->getType ();
  }
  dbi_free_result ( $res );
}

// Make sure this user is allowed to look at this file.
// If the blob is associated with an event, then the user must be able
// to view the event in order to access this file.
// TODO: move all this code (and code in view_entry.php) to a common
// function named can_view_event or something similar.
$can_view = false;
$is_my_event = false;
$is_private = $is_confidential = false;
$log = getGetValue ( 'log' );
$show_log = ! empty ( $log );

if ( empty ( $id ) )
  $can_view = true; // not associated with an event

if ( ! empty ( $id ) && empty ( $error ) ) {
  if ( $is_admin || $is_nonuser_admin || $is_assistant )
    $can_view = true;

  if ( empty ( $id ) || $id <= 0 || ! is_numeric ( $id ) )
    $error = str_replace ( 'XXX', $id, $invalidIDStr );

  if ( empty ( $error ) ) {
    // is this user a participant or the creator of the event?
    $res = dbi_execute ( 'SELECT we.cal_id FROM webcal_entry we,
      webcal_entry_user weu WHERE we.cal_id = weu.cal_id AND we.cal_id = ?
      AND ( we.cal_create_by = ? OR weu.cal_login = ? )',
      array ( $id, $login, $login ) );
    if ( $res ) {
      $row = dbi_fetch_row ( $res );
      if ( $row && $row[0] > 0 ) {
        $can_view = true;
        $is_my_event = true;
      }
      dbi_free_result ( $res );
    }

    if ( ($login != '__public__') && ($PUBLIC_ACCESS_OTHERS == 'Y') ) {
      $can_view = true;
    }
    if ( ! $can_view ) {
      $check_group = false;
      // if not a participant in the event, must be allowed to look at
      // other user's calendar.
      if ( $login == '__public__' ) {
        if ( $PUBLIC_ACCESS_OTHERS == 'Y' )
          $check_group = true;
      } else {
        if ( $ALLOW_VIEW_OTHER == 'Y' )
          $check_group = true;
      }
      // If $check_group is true now, it means this user can look at the
      // event only if they are in the same group as some of the people in
      // the event.
      // This gets kind of tricky. If there is a participant from a different
      // group, do we still show it?  For now, the answer is no.
      // This could be configurable somehow, but how many lines of text would
      // it need in the admin page to describe this scenario?  Would confuse
      // 99.9% of users.
      // In summary, make sure at least one event participant is in one of
      // this user's groups.
      $my_users = get_my_users ();
      $cnt = count ( $my_users );
      if ( is_array ( $my_users ) && $cnt ) {
        $sql = 'SELECT we.cal_id FROM webcal_entry we, webcal_entry_user weu
          WHERE we.cal_id = weu.cal_id AND we.cal_id = ?
          AND weu.cal_login IN ( ';
        $query_params = array ();
      $query_params[] = $id;
      for ( $i = 0; $i < $cnt; $i++ ) {
          if ( $i > 0 ) {
            $sql .= ', ';
          }
          $sql .= '?';
          $query_params[] = $my_users[$i]['cal_login'];
        }
        $res = dbi_execute ( $sql . ' )', $query_params );
        if ( $res ) {
          $row = dbi_fetch_row ( $res );
          if ( $row && $row[0] > 0 )
            $can_view = true;

          dbi_free_result ( $res );
        }
      }
      // If we didn't indicate we need to check groups, then this user
      // can't view this event.
      if ( ! $check_group && ! access_is_enabled ()  )
        $can_view = false;
    }
  }
  $hide_details = ( $login == '__public__' &&
    ! empty ( $OVERRIDE_PUBLIC ) && $OVERRIDE_PUBLIC == 'Y' );

  // If they still cannot view, make sure they are not looking at a nonuser
  // calendar event where the nonuser is the _only_ participant.
  if ( empty ( $error ) && ! $can_view && ! empty ( $NONUSER_ENABLED ) &&
    $NONUSER_ENABLED == 'Y' ) {
    $nonusers = get_nonuser_cals ();
    $nonuser_lookup = array ();
    for ( $i = 0, $cnt = count ( $nonusers ); $i < $cnt; $i++ ) {
      $nonuser_lookup[$nonusers[$i]['cal_login']] = 1;
    }
    $res = dbi_execute ( 'SELECT cal_login FROM webcal_entry_user
      WHERE cal_id = ? AND cal_status in ( \'A\', \'W\' )', array ( $id ) );
    $found_nonuser_cal = $found_reg_user = false;
    if ( $res ) {
      while ( $row = dbi_fetch_row ( $res ) ) {
        if ( ! empty ( $nonuser_lookup[$row[0]] ) )
          $found_nonuser_cal = true;
        else
          $found_reg_user = true;
      }
      dbi_free_result ( $res );
    }
    // Does this event contain only nonuser calendars as participants?
    // If so, then grant access.
    if ( $found_nonuser_cal && ! $found_reg_user )
      $can_view = true;
  }
  if ( empty ( $error ) && ! $can_view )
    $error = print_not_auth (8);
}

if ( ! empty ( $error ) ) {
  print_header ();
  echo print_error ( $error, true) . print_trailer ();
  exit;
}

$disp = ( $type == 'A' ? 'attachment' : 'inline' );

// Print out data now.
Header ( 'Content-Length: ' . $size );
Header ( 'Content-Type: ' . $mimetype );

$description = preg_replace ( "/\n\r\t+/", ' ', $description );
Header ( 'Content-Description: ' . $description );

// Don't allow spaces in filenames.
//$filename = preg_replace ( "/\n\r\t+/", "_", $filename );
//Header ( "Content-Disposition: $disp; filename=$filename" );
Header ( 'Content-Disposition: filename=' . $filename );

echo $filedata;
exit;

?>

Added docadd.php.











































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
<?php
/* $Id: docadd.php,v 1.20.2.3 2007/11/12 15:40:30 umcesrjones Exp $
 *
 * Page Description:
 *  This page will handle adding blobs into the database. It will
 *  present the form page on a GET and handle updating the database
 *  on a POST.
 *  This includes:
 *    Add comment to an event
 *    Add attachment to an event
 *
 * Input Parameters:
 *  For GET:
 *    id - event id (optional for some types)
 *    type - C=comment, A=attachment
 *  For POST:
 *    id - event id (optional for some types)
 *    type - C=comment, A=attachment
 *    description - (for type=C and A)
 *    comment - (for type=C)
 *    FileName - (for type=A)
 *
 * Comments:
 *  TODO: add email notification when attachment or comment is added
 */
include_once 'includes/init.php';

$id = getValue ( 'id', '-?[0-9]+' );
$type = getValue ( 'type' );
$user = getValue ( 'user' );
$error = '';

switch ( $type ) {
  case 'C':
    if ( empty ( $id ) )
      $error = 'No id specified';
    $title = translate ( 'Add Comment' );
    break;
  case 'A':
    if ( empty ( $id ) )
      $error = 'No id specified';
    $title = translate ( 'Add Attachment' );
    $upload = ini_get ( 'file_uploads' );
    $upload_enabled = ! empty ( $upload ) &&
      preg_match ( "/(On|1|true|yes)/i", $upload );
    if ( ! $upload_enabled ) {
      $error = 'You must enable file_uploads in php.ini';
    }
    break;
  default:
    $error = 'Invalid type';
    break;
}

$can_add = false;
if ( $is_admin )
  $can_add = true;

// Get event details if this is associated with an event
if ( empty ( $error ) && ! empty ( $id ) ) {
  // is this user a participant or the creator of the event?
  $res = dbi_execute ( 'SELECT we.cal_id
    FROM webcal_entry we, webcal_entry_user weu
    WHERE we.cal_id = weu.cal_id AND we.cal_id = ?
    AND ( we.cal_create_by = ? OR weu.cal_login = ? )',
    array ( $id, $login, $login ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    if ( $row && $row[0] > 0 )
      $is_my_event = true; // user is participant

    dbi_free_result ( $res );
  }
}

if ( $type == 'A' ) {
  if ( empty ( $ALLOW_ATTACH ) || $ALLOW_ATTACH != 'Y' )
    $error = print_not_auth (9);
  else if ( empty ( $error ) && $ALLOW_ATTACH_PART == 'Y' && $is_my_event )
    $can_add = true;
  else if ( $ALLOW_ATTACH_ANY == 'Y' )
    $can_add = true;
} else if ( $type == 'C' ) {
  if ( empty ( $ALLOW_COMMENTS ) || $ALLOW_COMMENTS != 'Y' )
    $error = print_not_auth (10);
  else if ( empty ( $error ) && $ALLOW_COMMENTS_PART == 'Y' && $is_my_event )
    $can_add = true;
  else if ( $ALLOW_COMMENTS_ANY == 'Y' )
    $can_add = true;
}
//check UAC
if ( access_is_enabled () ) {
  $can_add = $can_add || access_user_calendar ( 'edit', $user );
}

if ( ! $can_add )
  $error = print_not_auth (6);

if ( ! empty ( $error ) ) {
  print_header ();
  echo print_error ( $error );
  echo print_trailer ();
  exit;
}

// Handle possible POST first
if ( empty ( $REQUEST_METHOD ) )
  $REQUEST_METHOD = $_SERVER['REQUEST_METHOD'];
if ( $REQUEST_METHOD == 'POST' ) {

  // get next id first
  $res = dbi_execute ( 'SELECT MAX( cal_blob_id ) FROM webcal_blob' );
  if ( ! $res )
    die_miserable_death ( str_replace ( 'XXX', dbi_error (),
      translate ( 'Database error XXX.' ) ) );
       $row = dbi_fetch_row ( $res );
  $nextid = ( ! empty ( $row ) ? $row[0] + 1 :  1 );
  dbi_free_result ( $res );

  if ( $type == 'C' ) {
    // Comment
    $description = getValue ( 'description' );
    $comment = getValue ( 'comment' );
    if ( ! dbi_execute ( 'INSERT INTO webcal_blob ( cal_blob_id, cal_id,
      cal_login, cal_name, cal_description, cal_size, cal_mime_type, cal_type,
      cal_mod_date, cal_mod_time, cal_blob )
      VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )', array ( $nextid, $id, $login,
        NULL, $description, 0, 'text/plain', 'C', date ( 'Ymd' ), date ( 'His' ),
        NULL ) ) )
      $error = db_error ();
    else {
      if ( ! dbi_update_blob ( 'webcal_blob', 'cal_blob',
        "cal_blob_id = $nextid", $comment ) )
        $error = db_error ();
      else {
        // success!  redirect to view event page
        activity_log ( $id, $login, $login, LOG_COMMENT, '' );
        do_redirect ( "view_entry.php?id=$id" );
      }
    }
  } else if ( $type == 'A' ) {
    // Attachment
    $description = getValue ( 'description' );
    if ( ! empty ( $_FILES['FileName'] ) )
      $file = $_FILES['FileName'];
    if ( empty ( $file['file'] ) )
      $error = 'File Upload error!<br />';

    //print_r ( $file ); exit;
    $mimetype = $file['type'];
    $filesize = $file['size'];
    $filename = $file['name'];
    $tmpfile = $file['tmp_name'];
    if ( empty ( $description ) )
      $description = $filename;

    $data = '';
    $fd = @fopen ( $tmpfile, 'r' );
    if ( ! $fd )
      die_miserable_death ( "Error reading temp file: $tmpfile" );
    if ( ! empty ( $error ) ) {
      while ( ! feof ( $fd ) ) {
        $data .= fgets ( $fd, 4096 );
      }
    }
    fclose ( $fd );

    $comment = getValue ( 'description' );
    if ( ! dbi_execute ( 'INSERT INTO webcal_blob ( cal_blob_id, cal_id,
      cal_login, cal_name, cal_description, cal_size, cal_mime_type, cal_type,
      cal_mod_date, cal_mod_time, cal_blob )
      VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )', array ( $nextid, $id, $login,
        $filename, $description, $filesize, $mimetype, 'A', date ( 'Ymd' ),
        date ( 'His' ), NULL ) ) )
      $error = db_error ();
    else {
      if ( ! dbi_update_blob ( 'webcal_blob', 'cal_blob',
        "cal_blob_id = $nextid", $data ) ) {
        $error = db_error ();
      } else {
        // success!  redirect to view event page
        activity_log ( $id, $login, $login, LOG_ATTACHMENT, $filename );
        do_redirect ( "view_entry.php?id=$id" );
      }
    }
  } else {
    die_miserable_death ( 'Unsupported type' ); // programmer error
  }

  if ( ! empty ( $error ) ) {
    print_header ();
    echo print_error ( $error );
    echo print_trailer ();
    exit;
  }
}

print_header ();
?>
<h2><?php echo $title;?></h2>

<?php if ( $type == 'C' ) {
  // Comment
?>
<form action="docadd.php" method="post" name="docform">
<input type="hidden" name="id" value="<?php echo $id?>" />
<input type="hidden" name="type" value="C" />

<table>

<tr><td class="aligntop"><label for="description">
  <?php etranslate ( 'Subject' )?>:</label></td>
  <td><input type="text" name="description" size="50" maxlength="127" /></td></tr>
<!-- TODO: htmlarea or fckeditor support -->
<tr><td class="aligntop"><label for="comment">
  <?php etranslate ( 'Comment' )?>:</label></td>
  <td><textarea name="comment" rows="15" cols="60" wrap="auto"></textarea></td></tr>
<tr><td colspan="2">
<input type="submit" value="<?php etranslate ( 'Add Comment' )?>" /></td></tr>
</table>
</form>

<?php } else if ( $type == 'A' ) {
  // Attachment
?>
<form action="docadd.php" method="post" name="docform" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?php echo $id?>" />
<input type="hidden" name="type" value="A" />
<table>
<tr class="browse"><td>
 <label for="fileupload"><?php etranslate ( 'Upload file' );?>:</label></td><td>
 <input type="file" name="FileName" id="fileupload" size="45" maxlength="50" />
<tr><td class="aligntop"><label for="description">
  <?php etranslate ( 'Description' )?>:</label></td>
  <td><input type="text" name="description" size="50" maxlength="127" /></td></tr>

<tr><td colspan="2">
<input type="submit" value="<?php etranslate ( 'Add Attachment' )?>" /></td></tr>

</table>
</form>

<?php }
echo print_trailer (); ?>

Added docdel.php.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<?php
/* $Id: docdel.php,v 1.14.2.4 2011/04/27 00:27:35 rjones6061 Exp $
 *
 * Page Description:
 *  This page will handle deletion of an entry in webcal_blob.
 *  This could be a comment or an attachment.
 *
 * Input Parameters:
 *  For GET:
 *    blid - unique id, corresponds to webcal_blob.cal_blob_id
 *
 * Security:
 *  Only the creator of the comment, the creator of the associated
 *  event, or an admin can delete.
 *  (An assistant can also delete their boss' documents.)
 * Comments:
 *  TODO: perhaps add email notification on this
 */
include_once 'includes/init.php';
include_once 'includes/classes/Doc.class';

$blid = getValue ( 'blid', '-?[0-9]+', true );
$can_delete = false; // until proven otherwise
$error = $name = $owner = $type = '';
$event_id = -1;

if ( $is_admin )
  $can_delete = true;

$res = dbi_execute ( Doc::getSQLForDocId ( $blid ) );
if ( ! $res )
  $error = db_error ();
else {
  if ( $row = dbi_fetch_row ( $res ) ) {
    $doc = new Doc ( $row );
    $event_id = $doc->getEventId ();
    $name = $doc->getName ();
    $owner = $doc->getLogin ();
    $type = $doc->getType ();
    if ( $owner == $login || user_is_assistant ( $login, $owner ) )
      $can_delete = true;
  } else
    // document not found
    $error = str_replace ( 'XXX', $blid, translate ( 'Invalid entry id XXX.' ) );

  dbi_free_result ( $res );
}

if ( empty ( $error ) && ! $can_delete && $event_id > 0 ) {
  // See if current user is creator of associated event
  $res = dbi_execute ( 'SELECT cal_create_by FROM webcal_entry WHERE cal_id = ?',
    array ( $event_id ) );
  if ( $res ) {
    if ( $row = dbi_fetch_row ( $res ) ) {
      $event_owner = $row[0];
      if ( $event_owner == $login || user_is_assistant ( $login, $event_owner ) )
        $can_delete = true;
    }
    dbi_free_result ( $res );
  }
}

if ( empty ( $error ) && ! $can_delete )
  $error = print_not_auth (6);

if ( empty ( $error ) && $can_delete ) {
  if ( ! dbi_execute ( 'DELETE FROM webcal_blob WHERE cal_blob_id = ?',
      array ( $blid ) ) )
    $error = db_error ();
  else {
    if ( $event_id > 0 ) {
      $removeStr = translate ( 'Removed' );
      if ( $type == 'A' )
        activity_log ( $event_id, $login, $login, LOG_ATTACHMENT, $removeStr
         . ': ' . $name );
      elseif ( $type == 'C' )
        activity_log ( $event_id, $login, $login, LOG_COMMENT, $removeStr );
    }
    if ( $event_id > 0 )
      do_redirect ( 'view_entry.php?id=' . $event_id );

    do_redirect ( get_preferred_view () );
  }
}
// Some kind of error...
print_header ();
echo print_error ( $error ) . print_trailer ();

?>

Added docs/WebCalendar-SysAdmin.html.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
     <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebCalendar System Administrator's Guide</title>
<style type="text/css">
body {
 background-color: #FFFFFF;
 font-family: Arial, Helvetica, sans-serif;
}
a {
 text-decoration: none;
}
dt {
 font-weight: bold;
 margin-left: 25px;
 margin-top: 20px;
}
.valid {
 border-width: 0px;
}
pre {
 font-family: courier, monospace;
 font-size: 14px;
 border: 1px solid #0000FF;
 background-color: #EEEEFF;
 padding: 4px;
 margin-left: 25px;
 margin-right: 25px;
}
td {
 background-color: #ddd;
 border: 1px solid #bbb;
 color: #000;
 vertical-align: top;
}
th {
 background-color: #eee;
 border: 1px solid #ccc;
 color: #000;
}
.colorheader {
 background-color: #000000;
 color: #FFFFFF;
 margin-left: 3px;
 margin-right: 3px;
 padding: 2px;
}
.newwin {
 border-width: 0px;
}
.ptip {
  background: #ddd;
  padding: 5px;
  border: 1px solid #aaa;
}
.tip {
 font-weight: bold;
 background-color: #FFFF00;
 border: 1px solid #000000;
 padding: 1px;
 padding-left: 5px;
 padding-right: 5px;
 margin-right: 10px;
}
.note {
 font-weight: bold;
 background-color: blue;
 color: #FFFFFF;
 border: 1px solid #000000;
 padding: 2px;
}
hr {
 margin-bottom: 7px;
}
h2 {
 background-color: #191970;
 color: #FFFFFF;
 padding: 5px;
}
.top {
 text-align: right;
}
</style>
</head>
<body>
<h1>WebCalendar System Administrator's Guide</h1>
<p><strong>WebCalendar Version: 1.2.7</strong></p>

<h2>Table of Contents</h2>
<ul>
 <li><a href="#intro">Introduction</a></li>
 <li><a href="#requirements">System Requirements</a></li>
 <li><a href="#fileunpacking">File Unpacking</a></li>
 <li><a href="#appsetup">Application Installation</a></li>
 <li><a href="#eventcal">Configuring as Event Calendar</a></li>
 <li><a href="#users">Creating Users</a></li>
 <li><a href="#reminders">Setting Up Email Reminders</a></li>
 <li><a href="#systemsettings">System Settings</a></li>
 <li><a href="#siteextras">Custom Event Fields</a></li>
 <li><a href="#faq">FAQ</a></li>
 <li><a href="#trouble">Troubleshooting</a></li>
 <li><a href="#help">Getting Help</a></li>
 <li><a href="#license">Licensing</a></li>
 <li><a href="#glossary">Glossary</a></li>
 <li><a href="#appendixA">Appendix A: Database Setup with phpMyAdmin</a></li>
 <li><a href="#appendixB">Appendix B: Database Setup</a></li>
 <li><a href="#appendixC">Appendix C: Setting Up Reminders on Windows</a></li>
 <li><a href="#appendixD">Appendix D: Displaying Upcoming Events on Your Site</a></li>
 <li><a href="#appendixE">Appendix E: How To Configure for LDAP</a></li>
 <li><a href="#appendixF">Appendix F: Manual Installation</a></li>
 <li><a href="#appendixG">Appendix G: Error Codes</a></li>
</ul>
<hr />

<a name="intro"></a>
<h2>Introduction</h2>

<p>WebCalender is an open source PHP-based multi-user calendar.</p>

 <p><strong>Features:</strong></p>
 <ul>
  <li>Multi-user support</li>
  <li>Group support</li>
  <li>View day-at-glance</li>
  <li>View month-at-glance</li>
  <li>View week-at-glance</li>
  <li>View year-at-glance</li>
  <li>View another user's calendar</li>
  <li>View multiple users' calendars at the same time</li>
  <li>View one or more users' calendar via layers on top of your own calendar</li>
  <li>Public calendar (that requires no login) where anonymous users
    submit events that are approved by an administrator</li>
  <li>Add/Edit/Delete users</li>
  <li>Add/Edit/Delete events/todos</li>
  <li>Repeating events</li>
  <li>Custom event fields</li>
  <li>Search interface for calendar entries</li>
  <li>User-configurable preferences for colors, 12/24 time format,
    Week start on Sun or Mon, default work hours</li>
  <li>Online help</li>
  <li>Checks for scheduling conflicts</li>
  <li>Support for multiple timezones</li>
  <li>Users can accept or reject events added by another user to their calendar</li>
  <li>Email reminders</li>
  <li>Email notifications for new events</li>
  <li>Support for 30 different languages:
  <ul>
   <li>Basque</li>
   <li>Bulgarian</li>
   <li>Catalan</li>
   <li>繁體中文(Big5)</li>
   <li>简体中文(GB2312)</li>
   <li>Czech</li>
   <li>Danish</li>
   <li>Deutsche (German)</li>
   <li>English</li>
   <li>Espa&#241;ol (Spanish)</li>
   <li>Estonian</li>
   <li>Fran&#231;ais (French)</li>
   <li>Galician</li>
   <li>Greek</li>
   <li>Hollands (Dutch)</li>
   <li>Holo (Taiwanese)</li>
   <li>Hungarian</li>
   <li>Icelandic</li>
   <li>Italiano (Italian)</li>
   <li>Japanese (EUCJP, SJIS)</li>
   <li>Korean</li>
   <li>Norsk (Norwegian)</li>
   <li>Polish</li>
   <li>Portuguese</li>
   <li>Portuguese/Brazil</li>
   <li>Romanian</li>
   <li>Русско (Russian)</li>
   <li>Suomalainen (Finnish)</li>
   <li>Svensk (Swedish)</li>
   <li>Turkish</li>
   <li>Welsh</li>
  </ul>
 </li>
 <li>Exporting to and importing from:
  <ul>
   <li>Palm Pilot</li>
   <li>iCalendar</li>
   <li>vCalendar</li>
   <li>hCalendar (import only, requires PHP5)</li>
  </ul>
 </li>
 <li>Authentication using:
  <ul>
   <li>web-based</li>
   <li>HTTP authentication</li>
   <li>LDAP</li>
   <li>NIS</li>
   <li>IMAP</li>
   <li>support for external application authentication ( Postnuke, Joomla ) </li>
  </ul>
 </li>
 <li>Activity log that tracks:
  <ul>
   <li>event creation</li>
   <li>event updates</li>
   <li>event acceptance</li>
   <li>event rejection</li>
   <li>email notifications</li>
   <li>email reminders</li>
   </ul>
 </li>
 <li>Synchronization and Syndication:
   <ul>
   <li>Two-way authenticated iCalendar (ics) sync </li>
   <li>Anonymous iCalendar (ics) publishing</li>
   <li>RSS 2.0 feed </li>
   </ul>
 </li>
</ul>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="requirements"></a>
<h2>System Requirements</h2>
 <ul>
  <li>PHP 4.1 - PHP 5: some features specific version:
    <ul>
      <li>two-way iCalendar sync: PHP 4.3+ </li>
      <li>hCalendar importing: PHP 5+ </li>
    </ul>
  </li>
  <li>Database (see <a href="#database">below</a>)</li>
  <li>CSS-enabled browser:
    <ul>
      <li>Microsoft Internet Explorer </li>
      <li>Mozilla Firefox </li>
      <li>Opera </li>
      <li>Apple Safari </li>
    </ul>
  </li>
  <li>JavaScript-enabled browser</li>
  <li>If not using HTTP-based authentication,
      then browser cookies are required</li>
 </ul>
 <p><strong>Recommended:</strong></p>
 <ul>
  <li>pilot-link (if exporting to Palm):
  <a href="http://sourceforge.net/project/?group_id=2158">http://sourceforge.net/project/?group_id=2158</a>&nbsp;<a href="http://sourceforge.net/project/?group_id=2158" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
 </ul>
 <p><a name="database">You must have one of the following databases installed</a>:</p>
 <ul>
  <li>MySQL</li>
  <li>Oracle 8+</li>
  <li>PostgreSQL</li>
  <li>Interbase</li>
  <li>MS SQL Server</li>
  <li>SQLLite (PHP5)</li>
  <li>IBM DB2 </li>
  <li>ODBC</li>
 </ul>

 <p class="ptip"><span class="tip">TIP</span>PHP ODBC includes support for Adabas D, Solid
   and Sybase SQL Anywhere as well as ODBC. PHP5 comes bundled with
   SQLite support. SQLite is an embedded file-based database. If your
   hosting service supports PHP5, you should be able to create as
   many SQLite databases as you like (since each database is just
   a file).</p>
 <p>For the database you choose, you must have its drivers built into
  PHP. For example, to use MySQL, PHP must be compiled with MySQL
  support (which is the default setting when installing PHP).
  See the PHP pages (<a href="http://www.php.net">www.php.net</a>&nbsp;<a href="http://www.php.net" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>)
  for more information on setting up PHP.</p>
 <p>No optional PHP packages (other than MySQL) are required for this
  application. However, PHP should be compiled with <tt>--enable-track-vars</tt>
  on some systems.</p>
 <p class="ptip"><span class="tip">TIP</span>If you want to use gradient background
   images, PHP must be compiled with the GD library. </p>

  <p>You can run PHP either as a CGI or an Apache module. You'll get better
  performance with PHP setup as a module. Not only will you not have to
  deal with the CGI performance hit, but you'll be able to use PHP's
  database connection pooling. Additionally, this application can use
  a form/cookie-based authentication or traditional HTTP authentication.
  For traditional HTTP authentication, PHP must be built as an Apache
  module.</p>
 <p>If you are planning on using email reminders, you will need to build
  PHP as a CGI in order to run the <tt>send_reminders.php</tt> script. I would
  strongly recommend building a module-based PHP for your web server
  and then a second PHP build to create the CGI version.</p>
 <p class="ptip"><span class="tip">TIP</span> Some Linux distributions come with both a module-based PHP
  with Apache and a standalone PHP binary.
  Check for <tt>/usr/bin/php</tt> to see if you already have the
  PHP standalone executable. If it's there, you can use
  the following command to see what version of PHP you have:
  <br /><br />
  <tt style="margin-left: 50px;">/usr/bin/php -v</tt>
 </p>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="fileunpacking"></a>
<h2>File Unpacking</h2>
 <p>Unpack the calendar software in its own directory somewhere where
  your web server will find it. (See your web server documentation for information.)</p>
 <p>By default, unpacking WebCalendar will create its own directory
  when you unpack it. The new directory name will typically
  contain the version name (such as <tt>WebCalendar-1.2.7</tt>).
  You can rename this directory after unpacking the files if you
  prefer a directory name like <tt>calendar</tt> or <tt>webcalendar</tt>.
  Keep in mind that unless you remap the directory (via your web server's
  configuration settings), it will be part of the URL for the calendar.</p>
 <div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appsetup"></a>
 <h2>Application Installation</h2>

 <p>WebCalendar now includes an installation script that will guide you through
 the entire installation process.
 It should run automatically when first accessing
 a new installation or when a major version upgrade has been performed.
 The installation
 script can always be rerun if needed by adding <tt>install/index.php</tt>
 to your base WebCalendar URL. </p>

 <h3>WebCalendar Installation Wizard: Step 1</h3>
 <p>When first run, the installation script will prompt you for a
 <em>Configuration Wizard Password</em> that will protect against unauthorized
 tampering. Until this password is set, your WebCalendar installation and possibly your database are vulnerable to attack. Once, you've set your password, be sure
 to write it down. If forgotten, the only way to recover is to manually edit the
 <tt>install/settings.php</tt> file.</p>

 <p>The installation script will now check several prerequisites and report the
 results. Any item that appears in <font color="#FF0000">RED</font> should be
  corrected before continuing.</p>

 <table cellpadding="2">
 <tr><th>Prerequisite Failed</th><th>Recommended Solution</th></tr>
 <tr>
   <td>PHP 4.1.0 or greater</td>
   <td>Upgrade your PHP installation</td>
 </tr>
 <tr>
   <td>Safe Mode* = Off</td>
   <td>If possible, change this setting in your <tt>php.ini</tt> file to <tt>Off</tt>.</td>
 </tr>
 <tr>
   <td>Safe Mode Allowed Vars*</td>
   <td>If unable to to set Safe Mode Off, then set safe_mode_allowed_vars to contain
   <tt>TZ</tt> in your <tt>php.ini</tt> file.
   </td>
  </tr>
  <tr><td colspan="2">* NOTE: If neither of the these settings pass testing, then
   your WebCalendar installation will be restricted to using the server's timezone
   setting only.</td>
 </tr>
 <tr>
   <td>File Uploads</td>
   <td>If disabled, then some features of WebCalendar will not function. This setting is configurable in your <tt>php.ini</tt> or <tt>httpd.conf</tt> files as <tt>file_uploads</tt></td>
 </tr>
 <tr>
   <td>CRYPT_STD_DES</td>
   <td>This setting should be able to be ignored. We now support multiple <tt>crypt</tt>
   algorithms. If this setting is not enabled and you experience difficulties logging in,
    please notify the WebCalendar development team.</td>
 </tr>
 <tr>
   <td>GD</td>
   <td>This library is required only if gradient background images are desired. Normally, PHP must be compiled with this option. Some installations only require it be enabled in your
   <tt>php.ini</tt> file.</td>
 </tr>
 <tr>
   <td>Session Check</td>
   <td>PHP Sessions are used during the installation process and are required
     for proper operation. Sessions can be configured in your <tt>php.ini</tt> file.
     If it's not possible to enable sessions, then you must manually install WebCalendar.
     Details are available in
   <a href="#appendixF">Appendix F</a></td>
 </tr>
 <tr>
   <td>Settings.php Status</td>
   <td>The installation script was either unable to create, or unable to write
     to your settings.php file. You will need to modify the permissions of the <tt>includes</tt>
    directory. On Linux/UNIX, you should change this directory to be read/write
     for all users (<tt>chmod 777 includes</tt>). On Windows, change this directory
      to have full access for all users using Windows Explorer.</td>
 </tr>

 </table>
 <h3>WebCalendar Installation Wizard: STEP 2</h3>

 <p>The installation script can create your WebCalendar database as well as create all the required tables and pre-populate them with the basic configuration data. These features are only available when using fully supported database types. See
 <a href="#appendixB">Appendix B</a> to manually create your database if needed.</p>

 <p><strong>Database Status</strong></p>
 <p>Displays the current status of your database settings as well the supported
 databases for your PHP installation.</p>

 <p><strong>Database Settings</strong></p>
<p>To configure your database access. Set the values for:</p>
 <table class="distinguish">
  <tr><th>Displayed Value</th><th>settings.php value</th><th>Comments</th></tr>
  <tr><td>
   Database Type</td><td>db_type</td>
  <td>
   One of "mysql", "oracle", "postgresql", "odbc",
   &quot;mssql&quot;, sqllite, db2,
   or "ibase"
  </td>
  </tr>
  <tr><td>
   Server</td><td>db_host</td><td>
   The hostname that database is running on.
   (Use localhost if it's the same machine as
   the web server.) (This variable is not used with ODBC, enter 'none')
   (Use 'none' if your db server does not use a TCP socket to connect)
   (If using a special PORT, you can specify it as HOST:PORT)
  </td></tr>
  <tr><td>
   Login</td><td>db_login</td><td>
   The database login
   (Not used for SQLite.)
  </td></tr>
  <tr><td>
   Database Name</td><td>db_password</td><td>
   The database password for the above login<br />
   (Use 'none' if your db server does not use a TCP socket to connect.)
   (Not used for SQLite.)
  </td></tr>
  <tr><td>
   Database Name</td><td>db_database</td><td>
   The name of the database that the calendar
   tables reside in. ("intranet" in the <a href="#dbsetup">examples above</a>.)
   For ODBC, this should be the DSN.
   For SQLite, this is the filename that will be used.
  </td></tr>
  <tr><td>
   Connection Persistence</td><td>db_persistent</td><td>
   Enable use of persistent (pooled) database connections.
   This should typically be enabled. This setting may be disabled for CGI installations.
  </td></tr>
  <tr><td>
   Database Cache Directory</td><td>db_cachedir</td>
   <td>
   To enable caching of database query results, enter a writable directory. This
     directory should NOT be in the webserver document path to prevent unauthorized
     access to cached  sensitive data such as passwords hashes and private event
     details.
    To disable this feature, leave this field blank.
    However, this feature is recommended to enhance your system's performance.
  </td>
  </tr>
 </table>
 <p>Click the <font color="#FF0000">Test Settings</font> button to perform the test your settings.</p>

 <p>Click the <font color="#FF0000">Create</font> button to have the installation
   script create your database. This option will only be available for fully
   supported database types. Retest your database settings if prompted to do
   so.</p>

 <p class="ptip"><span class="tip">TIP</span>If this step does not complete
   properly, then you will have to manually create your database. Detailed instructions
   can be found in <a href="#appendixB">Appendix B</a>. Then rerun the installation
   script to continue the installation.</p>

 <h3>WebCalendar Installation Wizard: STEP 3</h3>
 <p>In this section we will perform the required database changes to bring your database up to the required level If you are using a fully supported database, this step will be performed automatically for you If not, the required SQL can be displayed and you should be able to cut &amp; paste it into your database server query window.</p>

 <p><strong>Database Status</strong></p>
 <p>This should display the current installed version of WebCalendar as well as the version being installed.</p>

 <p><font color="#FF0000"><strong>The following database actions are required</strong>
 </font></p>

 <p>If using a fully supported database type, clicking the <strong>Update Database</strong> button  will create any tables required for this installation or upgrade. If this feature is
 not supported, then this button will not be available.</p>

<p>The <strong>Display Required SQL</strong> button will always be available
  and if clicked will display the required SQL text that can then be cut &amp; pasted
  into the SQL query window of your database program. If using the approach,
  please rerun the installation script after completing your required database
  updates.</p>

 <p class="ptip"><span class="tip">TIP</span>If this step does not complete properly,
   then you will have to manually create your database tables. Detailed instructions
   can be found in <a href="#appendixF">Appendix F</a>. Then rerun the installation
   script to continue the  installation.</p>

 <h3>WebCalendar Installation Wizard: STEP 4</h3>

<p><strong>Timezone Conversion</strong></p>
<p>If upgrading WebCalendar from a previous version, you may be prompted to perform a Timezone Conversion. WebCalendar version 1.0.4 and earlier stored event date and time in the server's
timezone. As of v1.1.0, all event date and time information is stored as UTC time. So, a one-time conversion of existing events will required to prevent event displayed times from
appearing incorrectly.</p>

<p><strong>Application Settings</strong></p>

<p>Create Default Admin Account: If checked, a DEFAULT ADMINISTRATOR account will be created with username:admin password:admin</p>

<p>Application Name: The default value <strong>Title</strong> will be translated into
 <strong>WebCalendar</strong> into the user's language. Any other entry will not be
translated unless entries are made into the appropriate language.txt files.</p>

<p>Server URL: This should be the full URL to access your WebCalendar installation.The trailing "/" is required for proper operation. If this field is left blank, WebCalendar will
calculate the proper value and store it in the database.</p>

<p>User Authentication: You can configure the calendar to run in single-user<a href="#g_singleuser">*</a> mode or
 multi-user<a href="#g_multiuser">*</a> mode. If this is your first time using the
 calendar, it's easier to try single-user. You can always switch to multi-user
 later. Leave <tt>single_user</tt> set to "false" (the default) for multi-user or set
 it to "true" and set the value of <tt>single_user_login</tt> to a login name of your liking
 to set the system to single-user mode. (And be sure to set the value of
 <tt>single_user_login</tt> to the login that you would choose if you decide to switch
 to multi-user mode some day.)</p>
 <p><span class="note">Note:</span> If you do decide to switch from single-user mode to multi-user mode, make sure you add in a user to the system for the login you set the
  <tt>single_user_login</tt> variable to. You will need to do this via the
  database (mysql, sqlplus, etc.)  Look in the <tt>tables-mysql.sql</tt>
  (or <tt>tables-oracle.sql</tt>, etc.) to see the example of adding in the "admin" user.</p>
 <p>If you are setting up a multi-user calendar, you will need to choose
  how your users are authenticated. You must change the settings of
  <tt>use_http_auth</tt> and <tt>user_inc</tt>
  to setup which authentication method to use.</p>
 <p>You currently have five choices:</p>
 <ol>
  <li>Web-based authentication (login/passwords verified in the WebCalendar database):<br />
   <tt>use_http_auth = false</tt><br />
   <tt>user_inc = user.php</tt>
  </li>
  <li>HTTP-based authentication (login/passwords verified by the web server):<br />
   <tt>use_http_auth = true</tt><br />
   <tt>user_inc = user.php</tt><br />
   ... and don't forget to setup your web server to handle user
   authentication.<br />
          <span class="note">Note:</span> In order to use HTTP-based authentication,
    PHP must be setup as a module for your server rather than a CGI.
  </li>
  <li>NIS-based authentication (login/passwords verified by NIS):<br />
   <tt>use_http_auth = false</tt><br />
   <tt>user_inc = user-nis.php</tt><br />
   Additional configuration settings will need to be set
   in <tt>includes/user-nis.php</tt>.
  </li>
  <li>LDAP-based authentication (login/passwords verified by LDAP server):<br />
   <tt>use_http_auth = false</tt><br />
   <tt>user_inc = user-ldap.php</tt><br />
   Additional configuration settings will need to be set
   in <tt>includes/user-ldap.php</tt>.
  </li>
  <li>IMAP-based authentication (login/passwords verified by IMAP server):<br />
   <tt>use_http_auth = false</tt><br />
   <tt>user_inc = user-imap.php</tt><br />
   Additional configuration settings will need to be set
   in <tt>includes/user-imap.php</tt>.
  </li>
 </ol>

<p>Read-Only: Determines whether events can be added to your WebCalendar.</p>

<p>Environment: Normally set this <strong>Production</strong>. Development will allow
more verbose sql logging and should not be used unless needed.</p>

<p>After saving your settings, you should be provided with a
<strong>Launch WebCalendar</strong>  button that will open WebCalendar in a separate
browser window.</p>

<p><strong>Congratulations! You have successfully installed WebCalendar on
your system.</strong></p>

    <p>Keep in mind that if you want to use reminders, you will need to
  setup the <tt>send_reminders.php</tt> script (see below) and keep your admin
  setting for "Email enabled" set to "Yes" on the admin settings page.</p>
    <p>At this point, your WebCalendar installation should be up and running.
  To access WebCalendar open up your favorite web browser and
  type in the URL. The URL will depend on where you installed WebCalendar.</p>

 <p class="ptip"><span class="tip">TIP</span> On a multi-user system, the only user account created
 during installation has the username of "admin" and a password of "admin". You should create
 a new admin account and delete this one for security reasons.</p>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>

<hr />

<a name="eventcal"></a>
<h2>Configuring as Event Calendar</h2>

<p>
  If you intend to use WebCalendar as an event calendar, you will
  need to enable "Public Access" in the System Settings with the following
  steps:</p>
   <ul>
    <li>Login to WebCalendar as an administrator (the default username is
        'admin' and password 'admin'). </li>
   <li>Click on the "Admin" link at the bottom of any page.</li>
   <li>Click on the "System Settings" button.</li>
   <li>Click on the "Public Access" tab.</li>
   <li>Select "Yes" for "Allow public access".</li>
  </ul>
<p>This will allow users to access WebCalendar without a username and
password. Only events that are created with the "Public User" as
an event participant will show up in your event calendar for users
who have not logged in. If events are not showing up on your public
calendar, make sure the events have the "Public User" as a participant
and the event has been approved.
</p>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>

<hr />

<a name="users"></a>
 <h2>Creating Users</h2>
 <p>After logging in as an admin user (the initial username is "admin" with
  password "admin"), you will see a common set of links at the bottom
  of each page. Follow these steps to create a new user:</p>
 <ol>
  <li>Login to WebCalendar as an admin user</li>
  <li>Click on the "Admin" link at the bottom of any WebCalendar page</li>
  <li>Click on the "Users" button</li>
  <li>Click on the "Add New User" link</li>
  <li>Fill out the form with details for the new user (email address is optional)</li>
  <li>Click on the "Save" button</li>
 </ol>
 <p class="ptip"><span class="tip">TIP</span> On a single-user system, you do not need to create any users.</p>
 <p class="ptip"><span class="tip">TIP</span> For an event calendar, you do not need to create a user for the "public user".</p>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="reminders"></a>
 <h2>Setting Up Email Reminders</h2>
 <p>PHP does not come with a utility for executing time-based jobs.
  So, in order to check periodically for email reminders, a shell
  script was written in PHP. You will need two things to get this working:</p>
 <ol>
  <li>You should have a version of PHP built as a CGI (so that you can run
    php from the command line). This does not mean you must build all
    of PHP as a CGI. You can still build PHP as a module for your web
  server and then build the CGI-based PHP later.<br />
    <span class="note">Note:</span> Many Linux distributions and some Windows LAMP packages
    come with the PHP built for CGI.</li>
  <li>You must setup cron (on Linux/UNIX) or something like cron for Windows
  to run the <tt>send_reminders.php</tt> script periodically.</li>
 </ol>
 <p>Building PHP as a CGI is outside the scope of these instructions. But,
  if you read the PHP instructions, you'll see that the default build
  settings will build the CGI-based PHP. If you really can't do this
  (perhaps you don't have permission to install anything new on the
  system), skip down a couple of paragraphs to an alternate solution
  that does not require PHP CGI.</p>
 <p>For Linux/UNIX users, add the following line to the crontab entry of
  a user. (This would be the same user that the web server
  process runs as.)</p>
 <pre><tt>1 * * * * cd /some/directory/webcalendar/tools; ./send_reminders.php</tt></pre>
    <p>Of course, replace the directory location to wherever the
  <tt>send_reminders.php</tt> file can be found. If you moved this out of the
  tools directory (which is recommended for security reasons),
  be sure to update <tt>send_reminders.php</tt> since it needs
  to know where to find other WebCalendar files.</p>
    <p>If you cannot setup PHP as a CGI or have no idea how, you can leave
  <tt>send_reminders.php</tt> in its current location and access it via a URL.
  IMHO, this is not the best choice, but it still works. Setup a cron
  job to access the URL. For Linux/UNIX users, add the following line to
  the crontab entry of a user.</p>
 <pre><tt>1 * * * * wget http://yourserverhere/webcalendardirectoryhere/tools/send_reminders.php &gt; /dev/null</tt></pre>
<p>Some users have reported the following works better for their configuration.</p>
<pre><tt>1 * * * * wget -q -O /dev/null http://yourserverhere/webcalendardirectoryhere/tools/send_reminders.php</tt>
</pre>
  <p>You should test this from the command line first to make sure your setup is
  correct. If you do not have <tt>wget</tt> installed on your system, you can use
  any tool (lynx, perl script, etc.) that is capable of making an HTTP request for this.</p>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="systemsettings"></a>
 <h2>System Settings</h2>
 <p>System Settings allows the administrator to control what features are available to users
 as well as default values for certain features.</p>
 <p>Many of these settings can be overridden by users in their Preferences (such
   as color). These user configurable settings are identified by
  <strong><em>Italics</em></strong>.</p>
 <h3>Settings</h3>
 <dl>
  <dt>Application Name</dt>
  <dd>Specifies the document title (typically displayed in the window title bar
  of most browsers)</dd>
  <dt>Server URL</dt>
  <dd>Specifies the base URL of the calendar. This information is needed to
  accurately include URLs in email messages (Notifications and Reminders).</dd>
  <dt>Home URL</dt>
  <dd>Specifies the URL to return to when exiting WebCalendar. If set, a new menu option will
  become visible in the menu.</dd>
  <dt><em>Language</em></dt>
   <dd>Specifies the default language setting for all users.</dd>
  <dt>Server Timezone Selection</dt>
   <dd>Allows you to manually set your server's WebCalendar timezone selection. This has
   no effect on the OS Timezone settings.</dd>
  <dt>Allow user to use themes</dt>
   <dd>Allows users to have access to pre-defined themes that can set color or user preference
   settings. There are a few examples available in the <tt>themes</tt> folder.</dd>
  <dt><em>Themes</em></dt>
   <dd>The default theme that will be applied to all users unless they make their own
   changes.</dd>
  <dt>Allow top menu</dt>
   <dd>Turns on the NEW menu system for all users.</dd>
  <dt>Date Selectors position</dt>
   <dd>Determines position of Date Pulldown Selectors. Either inside the NEW
     menu or in their original location at the bottom of the calendar.</dd>
   <dt><em>Menu theme</em></dt>
   <dd>Theme to be used with NEW menu.</dd>
  <dt><em>Fonts</em></dt>
   <dd>Specifies your preferred font. Multiple font names should be comma-separated.</dd>
  <dt><em>Custom script/stylesheet</em></dt>
   <dd>Place any custom stylesheet information or JavaScript that will
       be included on all WebCalendar pages.</dd>
  <dt><em>Custom header</em></dt>
   <dd>The custom header allows you to specify HTML to be placed after
       the &lt;body&gt; tag but before any WebCalendar content and
       included on all WebCalendar pages.</dd>
  <dt><em>Custom trailer</em></dt>
   <dd>The custom trailer allows you to specify HTML to be placed after
       the WebCalendar content but before the &lt;/body&gt; tag and
       included on all WebCalendar pages.</dd>
 <dt>Allow external file for header/script/trailer</dt>
   <dd>If enabled, then the Custom header and Custom trailer settings
       can specify a filename on the server rather than HTML.</dd>
  <dt>Allow user to override header/trailer</dt>
   <dd>If enabled, then users can add their own custom HTML for
       both the header (top of the page) and trailer (bottom of the page)
       to customize the appearance of all pages.</dd>
  <dt><em>Preferred View</em></dt>
   <dd>Specify if users should see the day, week, month, or year after logging in.</dd>
  <dt><em>Display small months</em></dt>
   <dd>Specifies whether small months are included in month, week, day views.</dd>
  <dt><em>Display weekends</em></dt>
   <dd>Specifies whether weekends are included in month, week, day, and views.</dd>
  <dt><em>Display all days in month view</em></dt>
   <dd>Specifies whether the complete month grid is filled with days from previous and
   next month.</dd>
  <dt>Display days with events in bold in month and year views</dt>
   <dd>Highlights and bolds the text for days containing events in the mini-calendars
   used in day, month and year calendars.</dd>
  <dt><em>Display description in printer day view</em></dt>
   <dd>If enabled, then the "printer friendly" view of the day view will include full event
    descriptions rather than just the event name.</dd>
  <dt>Display Common Use Date/Times as GMT</dt>
   <dd>Sets the timezone to used for General Purpose dates. Either GMT of the Server
   timezone will be selected.</dd>
   <dt><em>Date format</em></dt>
   <dd>Specifies the default format for displaying dates. These are defined in
     file
   <tt>includes/date_formats.php</tt> and if <strong>LANGUAGE DEFINED</strong> is selected
   then the format will be adjusted based on the format in the user's language.txt file.</dd>
   <dt><em>Time format</em></dt>
   <dd>Specifies the default time format as either 12-hour (3:45pm) or 24-hour (15:14)</dd>
   <dt><em>Display 00 minutes always</em></dt>
   <dd>Specifies whether times on the hour ( 10:00 ) are displayed with trailing 00.</dd>
  <dt><em>Entry interval</em></dt>
  <dd>Specify the default options for entry start and stop times. This values will also
  determine the display resolution of timebar views as well as user availability.</dd>
  <dt><em>Time interval</em></dt>
  <dd>Specify the default number of minutes each time block represents in the day and
  week display</dd>
  <dt><em>Auto-refresh calendars</em></dt>
  <dd>If set to "yes," the day, week, and month pages will automatically
  reload after a specified duration</dd>
  <dt><em>Auto-refresh time</em></dt>
  <dd>Specifies how long to wait before the auto-refresh should force a page
  to be reloaded</dd>
  <dt>Require event approvals</dt>
  <dd>If enabled, then events added to one user's calendar by another
      user will require approval.</dd>
  <dt><em>Display unapproved</em></dt>
  <dd>Specifies whether events that have been added to a calendar but not yet
  approved should display on the calendar (in a different color)</dd>
  <dt><em>Display week number</em></dt>
   <dd>Specifies whether the week number should be displayed in month and week views</dd>
  <dt><em>Week starts on</em></dt>
   <dd>Specifies if week start on Sunday or Monday</dd>
  <dt><em>Work hours</em></dt>
   <dd>Specifies the default time range to display in day and week views</dd>
  <dt>Disable Pop-Ups</dt>
   <dd>Determines whether event pop-ups are displayed.</dd>
  <dt>Disable Location field</dt>
   <dd>Determines whether to use the Location field for events.</dd>
  <dt>Disable Priority field</dt>
   <dd>If enabled, the Priority field will not be used</dd>
  <dt>Disable Access field</dt>
   <dd>If enabled, the Access field will not be used</dd>
  <dt>Disable Participants field</dt>
  <dd>If enabled, the Participants field will not be used, and users will not be
  able to add events to any calendar other than their own.</dd>
  <dt>Disable Repeating field</dt>
   <dd>If enabled, users will not be able to create repeating events</dd>
  <dt>Display Site Extras in popup</dt>
  <dd>If enabled, custom event fields configured in <tt>site_extras.php</tt>
      will appear in the mouse-over popups containing additional
      event information.</dd>
  <dt>Display Participants in popup</dt>
  <dd>If enabled, event participants will be included in popup details.</dd>
  <dt>Allow HTML in Description</dt>
  <dd>Allow the use of HTML in the description field when creating events. In addition, with the addition of either of two optional packages (HTMLArea or FCKEditor), you can have a WYSIWYG interface. These packages are available on <a href="http://www.k5n.us/webcalendar.php?topic=Add-Ons">WebCalendar's Home Page</a></dd>
  <dt>Allow viewing other user's calendars</dt>
   <dd>If enabled, users will be able to view the calendar of another user</dd>
  <dt>Include add event link in views</dt>
  <dd>If enabled, Views will include a link to quickly add events to the
  specified user's calendar.</dd>
  <dt>Remember last login</dt>
   <dd>If enabled, when a returning calendar user reaches the login page, their login name will be pre-filled with the last login username that they entered. (The password field will still be blank.)</dd>
  <dt>Check for event conflicts</dt>
   <dd>Specifies if the system should check for scheduling conflicts when a user adds or updates an event.</dd>
  <dt>Conflict checking months</dt>
   <dd>If conflict checking is enabled, this specifies how many months past the initial date the system will check for conflicts when a user adds or updates a repeating event.</dd>
  <dt>Allow users to override conflicts</dt>
   <dd>If enabled, users will be warned when there is an event conflict and be presented with the option of scheduling the event anyhow.</dd>
  <dt>Limit number of timed events per day</dt>
   <dd>If enabled, users can be limited to a specific number of timed events per day</dd>
  <dt>Maximum timed events per day</dt>
   <dd>Specifies that maximum number of events that can be scheduled in one day of any one user.</dd>
   <dt>Specify timed event length by</dt>
   <dd>Allows you to configure event lengths to be specified
       by either duration or end time.</dd>
   <dt>Brief Description Length</dt>
   <dd>Specifies the maximum numbers of characters to display in calendar views.</dd>
   <dt><em>Display Lunar Phases in month view</em></dt>
   <dd>Show Lunar Calendar icons in month view. This will not use existing event space.</dd>
   <dt><em>Disable Cross-Day Events</em></dt>
   <dd>Determines whether to display events that cross user's day boundary as
     multiple  events.</dd>
 </dl>
 <h3>Public Access</h3>
 <dl>
   <dt>Allow public access</dt>
  <dd>If enabled, anonymous users will be able to view the public access calendar without logging in.</dd>
  <dt>Public access visible by default</dt>
  <dd>If enabled, user's can go to the public access page without having to select it.</dd>
  <dt>Public access is default participant</dt>
  <dd>If enabled, public access will be added to every event  created.</dd>
  <dt>Public access can view other users</dt>
  <dd>If enabled, public access user's will be able to see the calendar of other WebCalendar users. <font color="#FF0000">Use with caution!</font></dd>
  <dt>Public access can add events</dt>
  <dd>If enabled, anonymous users will be able to submit new events</dd>
  <dt>Public access new events require approval</dt>
  <dd>If enabled, events submitted to the public access calendar (by anonymous users) will require approval by an admin user. If not enabled, then new events will appear on the public access calendar as soon as they are submitted.</dd>
  <dt> Public access can view participants</dt>
  <dd>If enabled, public access users can view the names of other participants for any event that public access is a participant. <font color="#FF0000">Use with caution!</font></dd>
  <dt>Override event name/description for public access</dt>
  <dd>If enabled, the value of the following setting will be used to mask the name and description of events.</dd>
  <dt>Text to display to public access</dt>
  <dd>Text to display as explained above.</dd>
 </dl>
  <h3>User Access Control</h3>
 <dl>
  <dt> User Access Control enabled</dt>
   <dd>User Access Control provides more advanced control of
       user access permissions.
       If enabled, a "User Access Control" button will appear on the
   main Admin page and/or on the Settings menu of the NEW top menu. This page
   will allow you to configure: </dd>
   <dd>
     <ul>
       <li>which functions in the system each user can access </li>
       <li>which user calendars each user can access
           (user A can edit events on user B's calendar, etc.)</li>
       </ul>
   </dd>
 </dl>
 <h3>Groups</h3>
 <dl>
  <dt>Groups enabled</dt>
   <dd>Specifies if group features should be enabled</dd>
  <dt>User sees only his group</dt>
   <dd>If enabled, users will be unaware of any users that are not in the same group as the user.</dd>
 </dl>
 <h3>NonUser Calendars</h3>
 <dl>
  <dt>Nonuser Calendars Enabled</dt>
   <dd>If enabled, you may create "nonuser calendars" in WebCalendar.
     A nonuser calendar is a calendar without a user login. It can
     be used to manage a resource like a conference room's availability.
     Or it can be used to place common events (like holidays) that multiple
     users may want to access as a layer.
     You will need to enable nonuser calendars in order to subscribe
     to remote iCalendar URLs from within WebCalendar (allowing the events
     from an iCalendar or hCalendar file elsewhere on the net to appear in your
     WebCalendar calendar.)
   </dd>
   <dt>Display in participants list at</dt>
   <dd>If enabled, then nonuser calendars can be selected as
       participants to events.</dd>
 </dl>
 <h3>Other</h3>
 <dl>
  <dt>Reports enabled</dt>
   <dd>If enabled, user's will be able to create and generate reports.</dd>
  <dt><em>Allow remote subscriptions</em></dt>
   <dd>If enabled, user's will be able enable their own subscription settings. There are currently two main ways to publish events with WebCalendar.</dd>
   <dd>
      <ul style="margin-left:70px;"><li ><strong>publish.php</strong> will provide outbound publishing to a calendar client</li>
   <li><strong>icalclient.php</strong> will provide two-way full synchronization between WebCalendar and another calendar client such as Sunbird, Apple iCal.
      (PHP 4.3+ required)</li>
      </ul></dd>

 <dt>Allow remote calendars</dt>
   <dd>If enabled, user's will be able to add a special type Non-User Calendar
     that includes a URL that point to the remote location. The user can manually
     synchronize the remote calendars if desired. In addition, <tt>tool/reload_remotes.php</tt>
     can be set up as a cron job to automatically reload all remote calendars
     as desired. Currently both iCalendar and hCalendar calendars can be consumed
     by WebCalendar. The  calendar type should be automatically detected based
     on the URL and calendar content. Users will need to create a layer to make
     a remote calendar visible on their calendars, just like regular Non-User
     Calendars.</dd>
   <dt>Enable RSS feed</dt>
   <dd>If enabled, a link is added to all pages that permits some browsers to
     create a persistent RSS feed to that page. Currently, only Firefox and IE
     7.0 supports this functionality. Also, the setting will enable the use of
     the rss.php script generate RSS feeds to RSS clients. User's will also be
     required to enable this feature in their respective preference settings.</dd>
   <dt>Categories enabled</dt>
   <dd>Specifies if category features should be enabled</dd>
   <dt>Category Icon Upload enabled</dt>
   <dd>Specifies if category icons can be uploaded by users. This requires that
     a folder named <tt>icons</tt> exist in the WebCalendar directory.</dd>
  <dt><em>Display small task list</em></dt>
   <dd>If enabled, a small task window will be displayed in the month and day calendars. These tasks are compatible with the VTODO component of RFC2445 (iCalendar)</dd>
  <dt><em>Display tasks in Calendars</em></dt>
   <dd>If enabled, tasks are displayed along with events in calendars. The date they appear is the due date but if the due date has passed without the task being completed, the task will shift to the current day.</dd>
<!--  <dt>Export VTIMEZONE in iCalendar (ics) files</dt>
   <dd>If enabled, a complete VTIMEZONE component will be exported with iCalendar (ics) files as necessary. This function requires considerable processing time, so it should not be enabled unless needed.</dd>
-->
  <dt>Allow external users</dt>
  <dd>If enabled, the create/edit event page will contain a text area to include
  the names (and optional email address) of event participants that are not calendar users.</dd>
  <dt>External users can receive email notifications</dt>
  <dd>If enabled, event participants entered into the External Participants area will receive email notifications at the same time as calendar users (if an email address was specified for the External Participant).</dd>
  <dt>External users can receive email reminders</dt>
  <dd>If enabled, event participants entered into the External Participants area will receive email reminders at the same time as calendar users (if an email address was specified for the External Participant).</dd>
  <dt>Allow self-registration</dt>
   <dd>If enabled, new users are permitted to setup their own accounts and log into WebCalendar without admin intervention. <font color="#FF0000">Use with caution!</font></dd>
  <dt>Restrict self-registration to blacklist</dt>
   <dd>If enabled, admin can configure the includes/blacklist.php to restrict or permit self-registration based on the user's IP. This will restrict access to existing users or new user's set up by admin. Details and examples are available in the top of the file.</dd>
   <dt>Generate passwords and send to new users</dt>
   <dd>If enabled, self-registration user's will be emailed a randomly generated password that they can then use to access WebCalendar normally. Hopefully, this will prevent some spammers and hackers from misusing the self-registration process.</dd>
   <dt>Allow file attachments to events</dt>
   <dd>If enabled, attachments can be uploaded and associated with events. The
     attachments are stored in the database, so care should be taken if performance
     is an issue. Additionally, permission may extended to participants and/or
     anyone.</dd>
   <dt>Allow comments to events</dt>
   <dd>If enabled, comments can be associated with events. Additionally,
   permission may extended to participants and/or anyone. </dd>
 </dl>
 <h3>Email</h3>
 <dl>
  <dt>Email enabled</dt>
   <dd>Specifies if email functionality should be enabled. If set to "No," then no email messages will be sent at any time.</dd>
  <dt>Default sender address</dt>
   <dd>Specifies the email originator to use when the system sends out email Notifications and Reminders</dd>
  <dt>Email Mailer</dt>
   <dd>Specifies the email program to use. (PHP mail, SMTP, or sendmail)</dd>
  <dt>SMTP Host name(s)</dt>
   <dd>Specifies the SMTP server name(s) or IP(s) if SMTP is selected above.</dd>
  <dt>SMTP Port Number</dt>
   <dd>Specifies the SMTP port number if SMTP is selected above. Default is 25.</dd>
  <dt>SMTP Authentication</dt>
   <dd>Specifies whether authentication is required if SMTP is selected above. Additionally,
   <strong>SMTP Username</strong> and <strong>SMTP Password</strong> will be required.</dd>
  <dt>Event reminders</dt>
     <dd>Specifies if email reminders for events that include a reminder should be sent</dd>
  <dt>Events added to my calendar</dt>
     <dd>Specifies if the system should send email when an event is added</dd>
  <dt>Events updated on my calendar</dt>
     <dd>Specifies if the system should send email when an event is updated</dd>
  <dt>Events removed from my calendar</dt>
     <dd>Specifies if the system should send email when an event is deleted</dd>
  <dt>Event rejected by participant</dt>
     <dd>Specifies if the system should send email when a participant to an event rejects the event</dd>
 </dl>
 <h3>Colors</h3>
 <dl>
  <dt>Allow user to customize colors</dt>
   <dd>Specifies whether color settings should be available to users in their Preferences</dd>
  <dt> Enable gradient images for background colors</dt>
     <dd>If enabled, the background of calendar table cells will be rendered with a gradient image based on the background color selected for that cell type. This option requires that php be compiled with the <strong>gd module</strong>.</dd>
     <dt>Document background</dt>
     <dd>Specifies the background color of all pages</dd>
  <dt>Document title</dt>
     <dd>Specifies the color of page title on each page</dd>
  <dt>Document text</dt>
     <dd>Specifies the default text color on each page</dd>
  <dt>My event text</dt>
     <dd>Specifies the default text color for the user's events</dd>
  <dt>Table grid color</dt>
     <dd>Specifies color of the lines that make HTML table grids on each page</dd>
  <dt>Table header background</dt>
     <dd>Specifies the default background for the heading of any HTML table</dd>
  <dt>Table header text</dt>
     <dd>Specifies the default text color for the heading of any HTML table</dd>
  <dt>Table cell background</dt>
     <dd>Specifies the background color for table cells</dd>
  <dt>Table cell background for current day</dt>
     <dd>Specifies the background color for the table cell containing the current
       date (<strong>today</strong>) </dd>
     <dt>Table cell background for days with events</dt>
   <dd>Specifies the background color of table cells containing events. This
     setting will not override the <strong>today</strong> setting and
     if identical to <strong>today</strong>, will be ignored. </dd>
   <dt>Table cell background for weekend</dt>
   <dd>Specifies the background color for table cells that represent a Saturday or Sunday</dd>
   <dt>Table cell background for other month</dt>
   <dd>Specifies the background color for table cells of other month days.</dd>
  <dt>Week number color</dt>
   <dd>Specifies the text color for week numbers (if enabled)</dd>
  <dt>Event popup background</dt>
   <dd>Specifies the background color of event popup areas</dd>
  <dt>Event popup text</dt>
   <dd>Specifies the text color of event popup areas</dd>
 </dl>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="siteextras"></a>
 <h2>Custom Event Fields</h2>
 <p>You may want to customize the event-specific fields found in
  the <tt>includes/site_extras.php</tt> field.
  If this is your first time using the calendar, you can skip
  this step and come back later since this step
  is <em>optional</em>.</p>
 <p>You can use this feature to add extra
  fields to your calendar events. For example, you can add a URL,
  a contact email address, or a pulldown containing predefined attributes.</p>
 <p>When defining a new custom field, the following types listed below
  are available. "Arg 1" and "Arg 2" have different meaning depending on the type
  of field. In some cases, "Arg 1" and "Arg 2" are not used.</p>
 <center>
  <table style="width: 100%;">
   <tr><th>
    Type</th><th>
    Description</th><th>
    Arg 1</th><th>
    Arg 2
   </th></tr>
   <tr><td>
    <tt>EXTRA_TEXT</tt></td><td>
    Allows the user to enter a single line of text</td><td>
    Specifies the size of the text form element as it would appear in the
    following ("NN" would be replaced with Arg 1):<br />
    &nbsp;&nbsp; <tt>&lt;input&nbsp;size="NN"&nbsp;...</tt></td><td>
    N/A
   </td></tr>
   <tr><td>
    <tt>EXTRA_MULTILINETEXT</tt></td><td>
    Allows the user to enter multiple lines of text</td><td>
    Specifies how many characters wide the textform element should be as it
    would appear in the following ("NN" would be replaced with Arg 1):<br />
    &nbsp;&nbsp; <tt>&lt;textarea&nbsp;cols="NN"&nbsp;...</tt></td><td>
    Specifies how many lines long the textform element should be as it would
    appear in the following ("NN" would be replaced with Arg 1):<br />
    &nbsp;&nbsp; <tt>&lt;textarea&nbsp;rows="NN"&nbsp;...</tt>
   </td></tr>
   <tr><td>
    <tt>EXTRA_URL</tt></td><td>
    Allows the user to enter a single line of text and will be displayed as a
    link when viewed</td><td>
    N/A</td><td>
    N/A
   </td></tr>
   <tr><td>
    <tt>EXTRA_DATE</tt></td><td>
    Allows the user to select a date using the standard date selection form
    elements</td><td>
    N/A</td><td>
    N/A
   </td></tr>
   <tr><td>
    <tt>EXTRA_EMAIL</tt></td><td>
    Allows the user to enter a single line of text and will be displayed as
    a mailto URL link</td><td>
    N/A</td><td>
    N/A
   </td></tr>
   <tr><td>
    <tt>EXTRA_USER</tt></td><td>
    Allows selection of a WebCalendar user from a pulldown list</td><td>
    N/A</td><td>
    N/A
   </td></tr>
   <tr><td>
    <tt>EXTRA_RADIO</tt></td><td>
    Allows selection of a single item from a group of radio buttons</td><td>
    Specifies the list of available options using the PHP <tt>array</tt></td><td>
   The default item that will be selected (from list above)
   </td></tr>
   <tr><td>
    <tt>EXTRA_SELECTION_LIST</tt></td><td>
    Presents the user with a selection list (single selection) to choose from</td><td>
    Specifies the list of available options using the PHP <tt>array</tt>
    function</td><td>
    0 indicates single selection, 1 indicates multiple selection and
    also the maximum size
   </td></tr>
   <tr><td>
    <tt>EXTRA_CHECKBOX</tt></td><td>
    Will display a checkbox control</td><td>
    N/A</td><td>
    N/A
   </td></tr>
  </table>
 </center>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="faq"></a>
 <h2>Frequently Asked Questions</h2>
 <dl>
<!-- cek: leave these comments here... extractfaqs.pl looks for them -->
<!-- START FAQ: Installation/Setup -->
  <dt>How do I setup PHP, MySQL and Apache on Windows?</dt>
   <dd>The easiest way to do this is to try one of the prepackaged bundles that will install all of these for you:
    <ul>
   <li><a href="http://www.apachefriends.org/en/xampp.html">XAMPP</a>&nbsp;<a href="http://www.apachefriends.org/en/xampp.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
   <li><a href="http://www.foxserv.net/">FoxServ</a>&nbsp;<a href="http://www.foxserv.net" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
   <li><a href="http://www.sokkit.net/">Sokkit</a>&nbsp;<a href="http://www.sokkit.net" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a> (formerly PHPTriad)</li>
    </ul>
  </dd>
  <dt>How do I setup PHP, MySQL and Apache on Mac OS X?</dt>
   <dd>You can use the built-in Apache/PHP installed on Mac OS X.
       However, this does not inlude MySQL.  An easier way to
       setup WebCalendar would be to use one of the following
       packages:
    <ul>
   <li><a href="http://www.apachefriends.org/en/xampp.html">XAMPP</a>&nbsp;<a href="http://www.apachefriends.org/en/xampp.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
    </ul>
  </dd>
 <dt>How do I setup PHP, MySQL and Apache on UNIX/Linux?</dt>
  <dd>There are many online instructions on how to do this. Here are a few:
    <ul>
   <li><a href="http://www.onlamp.com/pub/a/php/2000/11/17/php_admin.html">ONLamp.com: Basic Installation of PHP on a Unix System</a>&nbsp;<a href="http://www.onlamp.com/pub/a/php/2000/11/17/php_admin.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
   <li><a href="http://www.devshed.com/Server_Side/PHP/SoothinglySeamless/">Developer Shed: The Soothingly Seamless Setup of Apache, SSL, MySQL and PHP</a>&nbsp;<a href="http://www.devshed.com/Server_Side/PHP/SoothinglySeamless/" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
   <li><a href="http://www.linuxhelp.net/guides/lamp/">Linux Help: LAMP Guide</a>&nbsp;<a href="http://www.linuxhelp.net/guides/lamp/" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
   <li><a href="http://www.php.net/manual/en/installation.php">PHP.net</a>&nbsp;<a href="http://www.php.net/manual/en/installation.php" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></li>
    </ul>
  </dd>
 <dt>I've finished the install. What is the login to WebCalendar?</dt>
  <dd>After the initial creation of the database tables, there will
    be a single user account created with the username "admin" and
    the password set to "admin" as well.
    <br /><span class="note">Note:</span> This account is intended to get your started.
    You should create a new admin account and delete this one.</dd>
 <dt><a name="samplepublic">I want to use WebCalendar as an events calendar for
    my organization. How do I set it up to do this?</a></dt>
  <dd>You will want to setup WebCalendar to use public access.
    <ol>
    <li>Setup your <tt>settings.php</tt> file as a multi-user
      system (see <a href="#appsetup">instructions</a>).</li>
    <li>In System Settings, set "Allow public access" to "Yes."</li>
    <li>If you want people to be able to submit new events
      through public access, set "Public access can add events"
      to "Yes."</li>
    <li>If you set "Public access can add events" to "Yes",
      set the setting for "Public access new events
      require approval" to your liking. If you set this to "Yes,"
      an admin user will need to approve any new events before
      they will appear on the public access calendar.</li>
    <li>Login using one of the accounts you have setup.
       Add a new event, and select "Public User" as one of the
       participants.</li>
    <li>If you have enabled "Require event approvals" in your
       System Settings, then you will need to approve the new
       event. Choose the "Unapproved Events" at the bottom
       of any page (you must be an admin user to access this).
       You will be presented with a list of unapproved events
       (for both the current user and for the Public User account).
       Approve the new event for the Public User.</li>
    <li>Go to the Login page. You will see a "Access public calendar"
       link that will bring you to the calendar for public access.</li>
    <li>By default, the index.php page should send users to
       the public calendar.</li>
    </ol>
  </dd>

 <dt>How can I add holidays to the calendar?</dt>
 <dd>There is no built-in support for holidays because it is
 not necessary. You can add holidays into WebCalendar by importing
 one of the many iCalendar holiday files that are freely available.
 A good resource for free iCalendar files is
 <a href="http://www.icalshare.com">iCalShare
        <img src="newwin.gif" alt="new" class="newwin" /></a>.
 For example, the U.S. holiday iCalendar file can be downloaded from:
 <blockquote>
 <a href="http://icalshare.com/article.php?story=20020912105939521">http://icalshare.com/article.php?story=20020912105939521
        <img src="newwin.gif" alt="new" class="newwin" /></a> </blockquote>
 If you don't want each individual user to have to import
 the holiday calendar, you can use nonuser calendars.
 First, make sure nonuser calendars are enabled in your
 system settings. Then, from Admin-&gt;Users, you can
 access nonuser calendars. Create a new nonuser calendar
 (such as "usholidays"). Then, notify your users that they
 can add this nonuser calendar as a layer to their own
 calendar in order to see the holidays. </dd>

 <dt>Why are deleted events still present in the database?</dt>
  <dd>When you delete an event from your calendar, it is not
    deleted from the database. Instead, it is marked as deleted.
    This allows the system administrator access to information
    even after it is deleted.</dd>
 <dt>Can I setup more than one public calendar?</dt>
  <dd>You cannot directly setup two public calendars. However,
    there are two options for emulating this type of functionality:
    <ul>
    <li>You can <a href="WebCalendar-UserManual.html#categories">create global categories</a> and point users to the calendar with only a certain category displayed.</li>
    <li>You can setup multiple NonUser calendars and enable
        public access viewing of other users' calendars.
        You can then link directly to the calendar of one of
        the NonUser calendars, or you can
        <a href="WebCalendar-UserManual.html#views">setup a view</a>
        that contains the calendar of one or more of the NonUser calendars.</li>
    </ul>
   </dd>
 <dt>How do I change the title "Public Access" at the top of
 the calendar?</dt>
  <dd>In the file <tt>translations/English-US.txt</tt>,
  change the line that says "Public Access" to what you want
  it to say on the right side.<br /><br />Example:
  <pre>Public Access: Foobar Event Calendar</pre>
  </dd>
 <dt>Can I embed WebCalendar as a component on another web page?</dt>
  <dd>WebCalendar is meant to be run as a standalone web application.
    You can customize the appearance of WebCalendar to match your existing
    site.
    To do this, In System Settings, set both "Custom header" and
  "Custom trailer" to "Yes" and press the "Edit" button to enter the
    header and trailer content.
    <br />
    If you are looking to just include a list of upcoming events in one
    of your web pages, you can use the <tt>upcoming.php</tt> page in
    WebCalendar to do this. Edit the top of this file to configure options.
    (These settings will likely move into System Settings in subsequent release.)
    You can then use an <tt>iframe</tt> elsewhere on your web site as
    in the example below:
    <pre>&lt;iframe height="250" width="300" scrolling="yes" src="upcoming.php"&gt;&lt;/iframe&gt;</pre>
    Include this HTML anywhere on any of your pages.
    By default, the events from the public calendar will be loaded (so
    you must have "Public Access" enabled in System Settings).
    You can override this with another user's calendar.
    (See <tt>upcoming.php</tt> for instructions on this.)
    <br /><br />
    If you would like to display a small calendar (like the ones on the month view), you can add the
    following example. There are some configuration options available in the top of this file as well.
    You can then use an <tt>iframe</tt> elsewhere on your web site as
    in the example below:
    <pre>&lt;iframe height="200" width="180" scrolling="yes" src="minical.php"&gt;&lt;/iframe&gt;</pre>
  </dd>
 <dt>How do I customize the appearance of WebCalendar so that it matches
     the rest of my site?</dt>
  <dd>You can customize the appearance of WebCalendar to match your existing
    site.
    To do this, In System Settings, set both "Custom header" and
    "Custom trailer" to "Yes", and press the "Save" button.
    Then click on the "Edit" button to enter your site content.
    The custom header will be included after the document's HTML
    <code>&lt;body&gt;</code> tag but before any WebCalendar content.
    The custom trailer will be included after the WebCalendar content
    and before the document's HTML <code>&lt;/body&gt;</code> tag.
    If you want to add JavaScript or Stylesheet data, you can use
    the "Custom script/stylesheet" option on the same System Settings page.
    Any content entered will be included within the document's HTML
    <code>&lt;head&gt;</code> section. </dd>
 <dt>How do I add a new translation?</dt>
  <dd>
  It's a fairly simple process. If you've ever translated a C-based app
     that used GNU's gettext tool, then you'll have no problem. The I18N
     support was based on GNU's <a href="http://www.gnu.org/software/gettext/gettext.html">gettext</a>&nbsp;<a href="http://www.gnu.org/software/gettext/gettext.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>. Here's what you need to do.
     <ol>
     <li>look in the "translations" directory</li>
     <li>copy the <tt>English-US.txt</tt> file into what you'd like to call your
       language data file. (e.g. <tt>cp English-US.txt French.txt</tt>)</li>
     <li>Now translate all the text to the _right_ of the ": " into the
       new language. Do <em>not</em> alter the text to the left of the ": ".</li>
     <li>When you're done making changes, move into the "tools" directory.
       Run the <tt>check_translation.pl</tt> script on your new data file to make
       sure you have all the needed translations.
       (e.g. <tt>perl check_translation.pl French</tt>)</li>
     <li>Add the new language to both the $languages array and the
       $browser_languages arrays defined in <tt>includes/translate.php</tt>.</li>
     <li>Test it out... </li>
  <li>Post a copy of your translation (along with your changes to <tt>includes/translate.php</tt>) to the <a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=303870">SourceForge Patches</a>&nbsp;<a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=303870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a> for WebCalendar.</li>
     </ol>
  </dd>
 <dt>How do I update an existing translation?</dt>
  <dd>Just open up the translation file in the <tt>translations</tt> directory
     with your favorite text editor (like vi, vim, emacs, pico, Notepad, etc.).
     In particular look for places where missing translations are indicated.
     All missing translations should be marked with a
  "&lt;&lt;&nbsp;MISSING&nbsp;&gt;&gt;" note.
  and typically the English version of the translation will also be included on the following line (as in the example below):
    <pre># &lt;&lt; MISSING &gt;&gt;
# Edit:
#</pre><br />
  For some text, an abbreviation may be used rather than the English text.
  In those cases, the full text will be noted as in the following example:
  <pre># &lt;&lt; MISSING &gt;&gt;
# custom-script-help:
# English text: Allows entry of custom Javascript or stylesheet text that
# will be inserted into the HTML "head" section of every page.
#</pre><br />
     When you're done making changes, move into the <tt>tools</tt> directory.
       Run the <tt>check_translation.pl</tt> script on your new data file to make
       sure you have all the needed translations:
  <pre><tt>perl check_translation.pl French</tt></pre>
     Post a copy of your translation to the
  <a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=303870">SourceForge Patches</a>&nbsp;<a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=303870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a> for WebCalendar.</dd>
<dt>During Import, I receive this error: Unknown Timezone: XXXXX defaulting to GMT.</dt>
<dd>This is a notice that your import file contained unknown timezone information.
  WebCalendar will simply save the event or task as GMT. You are encouraged to
  submit these notices as <a href="https://sourceforge.net/projects/webcalendar/">Bug Reports to SourceForge</a>, so that WebCalendar can improve its TZID support.</dd>

<!-- END FAQ -->
 </dl>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="trouble"></a>
 <h2>Troubleshooting</h2>
    <dl>
<!-- cek: leave these comments here... extractfaqs.pl looks for them -->
<!-- START FAQ: Troubleshooting -->
 <dt>I get error messages about undefined variables when I try to view any page.</dt>
  <dd>On newer versions of PHP, the default setting of PHP is to display
    messages when an undefined variable is referenced. To prevent
    these messages from being displayed, change the setting of <tt>error_reporting</tt>
    in your <tt>php.ini</tt> file to be:
    <pre>error_reporting = E_ALL &amp; ~E_NOTICE</pre>
    Alternately, you can disable any error messages from being displayed
    in the browser and have them logged to a file. (See the comments
    included in the <tt>php.ini</tt> file for instructions on how to do this.)</dd>
 <dt><a name="dbCacheError">I receive an error message saying "Error removing temporary file" or "Cache error".</a></dt>
   <dd>This indicates that a file in your database cache directory could not be
   deleted or created.
   The quickest solution to this problem is to not use the database
   cache.  Simply remote the <tt>db_cachedir</tt> line from
   <tt>includes/settings.php</tt> with a simple text editor.
   This error is most common when the <tt>send_reminders.php</tt> script
   is run from a cron job under a different system account than the
   PHP application server is running under.  This causes files created by
   the <tt>send_reminders.php</tt> script to be owned by a different
   user than normal, preventing the PHP application from being able to
   remove the files when needed.
</dd>
 <dt>I receive an error message saying "Failed opening 'includes/...' for inclusion ..."</dt>
   <dd>You may have to modify the <tt>include_path</tt> setting
       in your <tt>php.ini</tt> file. Most users do not need to do this,
       but some PHP installs seem to require it. You will need to
       add the WebCalendar directory to the list of directories
       for <tt>include_path</tt>.</dd>
 <dt>I get an error message from PHP saying "Call to undefined function: ..."</dt>
  <dd>This tells you that your version of PHP is missing something that
    WebCalendar needs. If the function mentioned is a database login
  function (<em>ociplogin</em>, <em>mysql_pconnect</em>, <em>ibase_connect</em>, <em>pg_pconnect</em>),
  then you probably do not have the needed support for your database
  compiled into PHP.
    If the function is not a database connect call, then check the
    <a href="http://www.php.net/manual/en/">PHP manual</a>&nbsp;<a href="http://www.php.net/manual/en/" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>
    to see if the function requires a specific version of PHP. You
    may have an out-dated version of PHP that requires upgrading.</dd>
 <dt>When I try and view certain pages, nothing happens for 30 seconds, then I get a time-out error.</dt>
  <dd>On slower or very busy servers, it can take some time for the server
    to get all the events. Most PHP installations have a built-in timeout
    out of 30 seconds and will interrupt any request that takes longer than
    that. This is most likely to happen on the year-long custom report or
    on the month view when layers are being used. If you have access,
    you can increase the time-out value for PHP in the <tt>php.ini</tt>
    file by changing the setting of the <tt>max_execution_time</tt> setting.</dd>
 <dt>I get an error message that says "Can't connect to local MySQL server through socket '/tmp/mysql.sock'."</dt>
  <dd>This is a PHP/MySQL configuration issue. The value of <tt>mysql.default_socket</tt>
  in your <tt>php.ini</tt> file must match the value of <tt>socket</tt> in your
  <tt>my.cnf</tt> file. Edit the <tt>php.ini</tt> file to fix this problem.</dd>
 <dt>I am not receiving any email messages from WebCalendar.</dt>
  <dd>WebCalendar sends two types of email messages:
    Notifications<a href="#g_notification">*</a> and Reminders<a href="#g_reminder">*</a>.
  Check the following if you are not receiving any email:
    <ol>
   <li>You have defined a valid SMTP server in your PHP configuration file
    <tt>php.ini</tt>. (The setting is "SMTP" in the "mail_function" section.)</li>
   <li>In WebCalendar's System Settings, you have set the "Email Enabled" setting to "Yes".</li>
   <li>In WebCalendar's System Settings, make sure you have the "Default sender address"
   to something.
   <br /><span class="note">Note:</span>
          Some mail system will reject mail that has a "From" address
          that is a different domain from the originating SMTP server.
          So, if your SMTP server is smtp.mydomain.com and your "Default sender address"
   is calendar@someotherdomain.com, some mail systems may bounce the mail back.</li>
       <li>For a Notification, make sure you have the type of Notification
           set to "Yes" in the user's Preferences.</li>
       <li>For a Reminder:
    <ul>
            <li>Make sure you have "Event reminders" set to "Yes" in the user's Preferences.</li>
     <li>Make sure you have <a href="#reminders">setup a cron job</a> to periodically
      run the <tt>send_reminders.php</tt> script.</li>
    </ul>
   </li>
    </ol>
  </dd>
 <dt>Some of the pages are displaying text in English rather than &lt;insert your language here></dt>
  <dd>The translations have been submitted at various points of WebCalendar development.
   Some have not been updated to include newer features.</dd>
 <dt>The text that I entered in the <a href="#siteextras">Custom Event Fields</a> is not being translated
  to different languages.</dt>
  <dd>You will need to add an entry in each of the translation files for any text you add
   into the Custom Event Fields.</dd>
 <dt>How do I get the most recent version of WebCalendar?</dt>
  <dd>You can download the latest public release from SourceForge's
  <a href="http://sourceforge.net/project/showfiles.php?group_id=3870">file list for WebCalendar</a>&nbsp;<a href="http://sourceforge.net/project/showfiles.php?group_id=3870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>.
  <br />
    You can download the latest development code from the CVS server using
  the <a href="http://sourceforge.net/cvs/?group_id=3870">instructions provided by SourceForge</a>&nbsp;<a href="http://sourceforge.net/cvs/?group_id=3870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>. (You will need a CVS client to do this.)</dd>
 <dt>How do I install a patch file listed on SourceForge's
    <a href="http://sourceforge.net/tracker?group_id=3870&amp;atid=303870">list of WebCalendar patches</a>&nbsp;<a href="http://sourceforge.net/tracker?group_id=3870&amp;atid=303870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>?</dt>
  <dd>Most patches are distributed as context diffs. That means they were produced using the UNIX <tt>diff</tt> command with the <tt>-C</tt> option. The patches are intended to be used with the <a href="http://www.fsf.org/software/patch/patch.html">GNU patch</a>&nbsp;<a href="http://www.fsf.org/software/patch/patch.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a> program. This program is standard on most Linux systems and can be obtained as part of the <a href="http://www.cygwin.com">Cygwin</a>&nbsp;<a href="http://www.cygwin.com" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a> package for Windows. Mac OS X will have the patch program installed if they install the developer tools CD.</dd>
 <dt>I forgot/lost my admin password. How can I reset it?</dt>
  <dd>The easiest way is to admin a new admin user and then use that
    new user to reset the password for your old admin account.
    Assuming you have deleted the original 'admin' login, you can use
    the following SQL to insert a new admin user into the database:
    <pre>INSERT INTO webcal_user ( cal_login, cal_passwd, cal_lastname,
cal_firstname, cal_is_admin ) VALUES
( 'admin', '21232f297a57a5a743894a0e4a801fc3', 'Administrator',
'Default', 'Y' );</pre>
    This will add a user with login 'admin' and password 'admin' to the database.
    If you still have a user named 'admin', then replace 'admin' in the above
    SQL with a different username.
  </dd>
 <dt>I get a database error indicating table <tt>webcal_config</tt> does not exist.</dt>
  <dd>This is the first table that WebCalendar tries to access, so it
   typically means one of the following:
   <ul>
    <li>You have not created the database tables as described in the instructions</li>
    <li>You have the wrong database name specified in your
    <tt>includes/settings.php</tt> file</li>
   </ul>
  </dd>
 <dt>I get a database error from MySQL that says "Client does not support authentication protocol."</dt>
  <dd>From the MySQL 5.0 Reference Manual:
  <blockquote>MySQL 5.0 uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older (pre-4.1) clients. If you upgrade the server from 4.0, attempts to connect to it with an older client may fail with the following message:
  <br /><br />
  Client does not support authentication protocol requested
  by server; consider upgrading MySQL client
  </blockquote>
  The <a href="http://dev.mysql.com/doc/refman/5.0/en/old-client.html">MySQL
    Reference Manual</a> has solutions for this problem.
  </dd>

<!-- END FAQ -->
</dl>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="help"></a>
 <h2>Getting Help</h2>
 <p>Try the Help/Troubleshooting forum for WebCalendar, hosted at SourceForge.net:</p>
 <pre><a href="https://sourceforge.net/forum/forum.php?forum_id=11588">https://sourceforge.net/forum/forum.php?forum_id=11588</a>&nbsp;<a href="http://sourceforge.net/forum/forum.php?forum_id=11588" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a></pre>
 <p>If you encounter a bug, please check the
  <a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=103870">list of open and pending bugs</a>&nbsp;<a href="http://sourceforge.net/tracker/?group_id=3870&amp;atid=103870" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>.
  If you do <strong>not</strong> see anything similar, submit a new bug.</p>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="license"></a>
 <h2>Licensing</h2>
 <p>WebCalendar is distributed under the open source
  <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a>&nbsp;<a href="http://www.gnu.org/licenses/gpl.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>.
  If you have questions about this license, please
  read their <a href="http://www.gnu.org/licenses/gpl-faq.html">GPL FAQ</a>&nbsp;<a href="http://www.gnu.org/licenses/gpl-faq.html" title="Open in new window" target="_new"><img src="newwin.gif" alt="new" class="newwin" /></a>.</p>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="glossary"></a>
 <h2>Glossary</h2>
 <dl>
  <dt><a name="g_activitylog">Activity Log</a></dt>
   <dd>A summary of recent updates to calendar data</dd>
  <dt><a name="g_assistant">Assistant</a></dt>
   <dd>A calendar user that has been designated by another calendar user
    (the Boss) to help manage their calendar</dd>
  <dt><a name="g_boss">Boss</a></dt>
   <dd>A calendar user that has designated another calendar user
    (the Assistant) to help manage his calendar</dd>
  <dt><a name="g_externaluser">External User</a></dt>
   <dd>A calendar participant that does not have a calendar user account</dd>
  <dt><a name="g_group">Group</a></dt>
   <dd>A mechanism of dividing up a large set of users into smaller sets of users</dd>
  <dt><a name="g_imap">IMAP</a></dt>
   <dd>Internet Message Access Protocol, an optional method of user authentication.</dd>
  <dt><a name="g_layer">Layer</a></dt>
   <dd>A function that allows a user to overlay another user's calendar
    on top of his own calendar so that the standard day, week and month
    pages show both his own and the layered user's events</dd>
  <dt><a name="g_ldap">LDAP</a></dt>
   <dd>LDAP (Lightweight Directory Access Protocol) is an Internet protocol
    used to maintain user directories</dd>
   <dt><a name="g_mulituser">Multi-User Mode</a></dt>
   <dd>When WebCalendar is configured in Multi-User Mode,
    there can be multiple user accounts, each with his
    own calendar. Unless Public Access is enabled, all users
    will be required to login before they can access the system.</dd>
  <dt><a name="g_nis">NIS</a></dt>
   <dd>NIS (Network Information Service) is a UNIX-based user authentication
    system for managing user directories in a network</dd>
  <dt><a name="g_nonuser">NonUser Calendar</a></dt>
   <dd>A participant to a calendar event that is not a calendar user. This is typically used either as a resource (conference room,
  laptop computer) that needs to be shared or as a shared calendar
  that other users overlay onto their own calendar using layers (company-wide calendar,
  holiday calendar, etc.)</dd>
  <dt><a name="g_notification">Notification</a></dt>
   <dd>An email message that is sent when an event is added, removed
    or updated in the user's calendar by another user</dd>
  <dt><a name="g_preferredview">Preferred View</a></dt>
   <dd>The standard page (day, week, month or year) that will
    be presented to the user after logging in
    (set in user <a href="#pref">Preferences</a>)</dd>
  <dt><a name="g_preferredview">Public Access</a></dt>
   <dd>A <a href="#systemsettings">System Setting</a> that will allow anonymous users
    to access the calendar.
    See the <a href="#samplepublic">simple instructions</a> for
    setting this up in the <a href="#faq">FAQ section</a>.
    (Requires WebCalendar to be configured in Multi-User Mode).</dd>
  <dt><a name="g_reminder">Reminder</a></dt>
   <dd>An email message that is sent before an event to remind
    the participant</dd>
  <dt><a name="g_singleuser">Single-User Mode</a></dt>
   <dd>When WebCalendar is configured in Single-User Mode,
    there is no concept of users. You will be managing a single
    calendar and no login will be required.
    Anyone accessing this calendar will have full privileges to
    view, add, edit and delete all events.</dd>
  <dt><a name="g_timeinterval">Time Interval</a></dt>
   <dd>The amount of time each "block" will represent in
    either the day or week view
    (set in user <a href="#pref">Preferences</a>)</dd>
  <dt><a name="g_uac">User Access Control (UAC)</a></dt>
   <dd>The fully configurable feature to allow extremely granular
   access control to user. This control applies to system options and
   features as well as other user's calendars.</dd>
  <dt><a name="g_view">View</a></dt>
   <dd>A customized page that presents the events of selected users</dd>
  <dt><a name="g_workhours">Work Hours</a></dt>
   <dd>The default hours to show in the week and day view where
    events are displayed in blocks of time (set in
    user <a href="#pref">Preferences</a>)</dd>
 </dl>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appendixA"></a>
 <h2>Appendix A: Using phpMyAdmin</h2>
<p>
If you have <a href="http://www.phpmyadmin.net">phpMyAdmin</a>
installed and configured to manage your MySQL database, use the
following steps to setup WebCalendar.
(The following information is based on phpMyAdmin version 2.6.1.)</p>
<ol>
<li>On the initial phpMyAdmin page, under the "MySQL" heading, the first
  option should be "Create new database."  Enter the name you have
  chosen for the database and press the "Create" button.
  (The default database name used by WebCalendar is "intranet".)
  After pressing the "Create" button, it should say:
  "Database &lt;your database name here&gt; has been created." </li>
<li>Click on the home icon (the small house) in the left-side
   navigation. This will bring you back to your phpMyAdmin home page.</li>
<li>(Optional) Create new MySQL user. If you already have
    a MySQL login that you would like to use, you can skip this step.</li>
<li><ul>
  <li>Click on the "Privileges" link under the "MySQL" heading.</li>
  <li>Below any existing users listed, click on the link "Add a new User."</li>
  <li>Fill in the details of your new database user.
      The default username for WebCalendar is "webcalendar"
      with a password of "webcal01".
      Leave the "Host" field set to "Any host".</li>
  <li>From the list of "Global privileges", be sure to select:
      SELECT, INSERT, UPDATE, DELETE, FILE, CREATE, ALTER, INDEX, DROP </li>
  <li>Click on the "Go" button.</li>
  <li>You should see a page that says "You have added a new user."</li>
</ul></li>
<li>Click on the "Databases" tab at the top of the page.</li>
<li>From the list of databases on the page, click on the name
    of the database that you created.</li>
<li>Click on the "SQL" tab at the top of the page.</li>
<li>At the bottom of the page, there is an area to upload a SQL file.
    Click on the "Browse" button and select the <tt>tables-mysql.sql</tt>
    file in the WebCalendar toplevel directory.
    Then, press the "Go" button.</li>
<li>The top of the page should say "Your SQL-query has been executed
    successfully."</li>
<li>You have now finished creating the WebCalendar database tables.</li>

</ol>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appendixB"></a>
 <h2>Appendix B: Database Setup</h2>
 <p>There are three steps in setting up the database:</p>
 <ol>
  <li>Creating the database</li>
  <li>Creating the user</li>
  <li>Creating the required tables</li>
 </ol>
 <p>Follow the steps outlined below for the database you are using.
  When complete, a single user account will be created
  with the <strong>login "admin" and password "admin"</strong>, which you are encouraged
  to use to create your own account.</p>
 <p><span class="note">Note:</span> In the examples below, text in <strong>bold</strong>
  represents text that you must type in.</p>
         <p><span class="note">Security:</span> The default values for database, login, and
  password (<strong>intranet</strong>, <strong>webcalendar</strong>, and <strong>webcal01</strong>) are for demonstration purposes only
  and should never be used in a production environment.</p>
 <h3 class="colorheader">MySQL</h3>
 <p>The following will create a database named "intranet".</p>
<pre><strong>mysqladmin create intranet</strong></pre>
 <p>Next, create the database user account that will be used to access the database.</p>
 <pre><strong>mysql --user=root mysql</strong>
mysql&gt; <strong>GRANT ALL PRIVILEGES ON *.* TO webcalendar@localhost
IDENTIFIED BY 'webcal01' WITH GRANT OPTION;</strong>
mysql&gt; <strong>FLUSH PRIVILEGES;</strong>
mysql&gt; <strong>QUIT</strong></pre>
 <p>If you will be accessing MySQL from a different machine than
  the one running the web server, repeat the command above
  and replace 'localhost' with the hostname of the other machine.</p>
 <p>Create the calendar tables using the supplied <tt>tables-mysql.sql</tt> file:</p>
 <pre><strong>mysql intranet &lt; tables-mysql.sql</strong></pre>
 <p>In the above example, "intranet" is the name of your database.</p>

 <p><span class="note">Note:</span> If you are using
 <a href="http://www.phpmyadmin.net">phpMyAdmin</a> to
 manage your MySQL database, follow the
 instructions in <a href="#appendixA">Appendix A</a>.</p>

 <h3 class="colorheader">Oracle</h3>
 <p>The following will create a tablespace named "webcalendar".
  From the command line, startup sqlplus and
  issue the following command:</p>
 <pre><strong>sqlplus</strong>
SQL&gt; <strong>CREATE TABLESPACE webcalendar
DATAFILE 'webcalendar.dat' SIZE 10M
AUTOEXTEND ON NEXT 10M MAXSIZE 40M;</strong></pre>
 <p>Next, create the database user account that will be used to access the database.</p>
 <pre><strong>sqlplus</strong>
SQL&gt; <strong>CREATE USER webcalendar IDENTIFIED BY webcal01
DEFAULT TABLESPACE webcalendar;</strong>
SQL&gt; <strong>GRANT dba TO webcalendar;</strong>
SQL&gt; <strong>quit</strong></pre>
 <p>Create the calendar tables using the supplied <tt>tables-oracle.sql</tt> file:</p>
 <pre><strong>sqlplus webcalendar/webcal01</strong>
SQL&gt; <strong>@tables-oracle;</strong>
SQL&gt; <strong>quit</strong></pre>

 <h3 class="colorheader">PostgreSQL</h3>
 <p>The following will create a database named "webcalendar".
  From the command line as the psql user: issue the following commands:</p>
  <pre>$ <strong>su postgres</strong>
# <strong>createdb webcalendar</strong>
# <strong>createuser --no-createdb --no-adduser -P webcalendar</strong>
# <strong>psql webcalendar webcalendar</strong>
<strong>\i tables-postgres.sql</strong>
<strong>\q</strong></pre>

 <h3 class="colorheader">Interbase</h3>
 <p>The following will create a database named "WEBCAL.gdb".
  From the command line, startup usql and
  issue the following command:</p>
 <pre><strong>CREATE DATABASE 'WEBCAL.gdb';</strong></pre>

 <p>Create the calendar tables using the supplied <tt>tables-ibase.sql</tt> file:</p>
 <pre><strong>isql
connect /path/WEBCAL.gdb;
input path/table-ibase.sql;</strong></pre>

 <h3 class="colorheader">ODBC</h3>
 <p>Setup will depend on which database you are using.
  When it comes time to create the tables,
  the <tt>tables-postgres.sql</tt> file should work for most
  databases.</p>
   <h3 class="colorheader">MSSQL</h3>
 <p>Create a database, <strong>intranet,</strong>  and add a user, <strong>webcalendar</strong>, to access this database. The user should be granted public, db_datareader,
   and db_datawriter privileges. Open SQL Query Analyzer then open
   the file <tt>tables-postgres.sql</tt>. Make sure you have identified <strong>intranet</strong> as the target database and Execute the contents of the sql file.</p>
          <div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>

<a name="appendixC"></a>
<h2>Appendix C: Setting Up Reminders on Windows</h2>

<p>You have two options to choose from when setting up email
   reminders on a Windows platform.
   You can either install a cron package for Windows,
   or you can use the Windows Task Scheduler.</p>

<h3>Installing a Cron Package</h3>
<p>
If you install a cron package for Windows, you will need to setup
to setup a cron job.
(UNIX cron is a tool for used to run tasks as specified times anywhere
from every minute to once a year.)</p>
<p>
First, you should create a <tt>sendreminders.bat</tt> file
that contains a single line:</p>
<pre>C:\your\path\to\php.exe C:\your\path\to\webcalendar\tools\send_reminders.php</pre>
<p>You can place this <tt>sendreminders.bat</tt> file anywhere on your
file system.</p>
<p>Next, you need to setup the cron job.
The crontab entry should look like
the following (replace with the correct path to your
newly created <tt>sendreminders.bat</tt> file):</p>

<pre>1 * * * * C:\your\path\to\sendreminders.bat</pre>

<p>The "1 * * * *" will tell the cron schedule to run this task
at 1 after the hour all day long (12:01am, 1:01am, 2:01am, etc.)
If you only want to run it once per day, you could use:</p>
<pre>1 4 * * * C:\your\path\to\sendreminders.bat</pre>
<p>This would tell the cron scheduler to run the task at 4:01am
every day.
For more information about the syntax of cron, check the documentation
for the package you have installed or
view the UNIX man page for crontab
(like <a href="http://www.rt.com/man/crontab.5.html"
  target="_blank">this one</a>).</p>

<p>There are many cron packages for Windows available.
   Below is a list of packages to choose from.
   (Note: use at your own risk. These links are provided
   for information only.)</p>

<ul>
  <li><a href="http://cronw.sourceforge.net/"
    target="_blank">CRONw</a> (open source) </li>
  <li><a href="http://www.gold-software.com/VisualCron-review11507.htm"
    target="_blank">VisualCron</a> (freeware)</li>
  <li><a href="http://www.nncron.ru"
    target="_blank">nnCron</a> (freeware and commercial versions)</li>
  <li><a href="http://surguy.net/articles/icron.xml"
    target="_blank">iCron</a> </li>
  <li><a href="http://p.clark.home.mindspring.com/jcron/index.html"
    target="_blank">jCron</a> (freeware) </li>
</ul>

<h3>Using the Windows Task Schedule</h3>

<p>Follow the steps listed below to setup a new task
   in the Windows Task Scheduler.
   (These instructions were created with Windows XP Professional.
   Other versions of Windows might be different.)</p>

<ol>

<li>Create a new batch file called <tt>sendreminders.bat</tt>.
    The contents of this file should be a single line:
    <pre>C:\your\path\to\php.exe C:\your\path\to\webcalendar\tools\send_reminders.php</pre>
  </li>

<li>On Windows XP, go to Control Panel</li>
<li>Double-click on "Scheduled Tasks."
  This brings up a window that says "Scheduled Task Wizard" </li>

<li>Click on "Browse..." </li>

<li>Select the location of your newly created
    <tt>sendreminders.bat</tt> file.</li>
<li>Click on "Open" </li>

<li>Change the name of the task. "WebCalendar Reminders" is a good name.
  </li>

<li>Select how often to perform this task. Select "Daily." </li>
<li>Click on "Next" </li>

<li>Select the start time, then click "Next".
    If you are planning on sending out reminders throughout the
    day, pick a time shortly after midnight. </li>

<li> Enter your user password as required. Click on "Next." </li>

<li> Select the checkbox "Open advanced properties". </li>
<li> Click on "Finish." </li>

<li> Under the "Schedule" tab, click on "Advanced." </li>

<li> Click on "Repeat Task" and fill in the details of how often
     the job should run.
     For example, you can set it to run "every 15 minutes", then
     click on "until" and set that time to 11:30pm.
  </li>
</ol>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appendixD"></a>
<h2>Appendix D: Displaying Upcoming Events on Your Site</h2>

<p>
If you would like to list upcoming events somewhere on a page on your site
(someplace other than the WebCalendar pages),
you can use the <tt>upcoming.php</tt> page to do this.
This page is intended to be included in other pages using the
<tt>iframe</tt> tag.</p>
<p>You may need to modify some of the variables near the top of
<tt>upcoming.php</tt> with a text editor:</p>
<table border="0" style="margin-left: 20px; margin-right: 20px;">

<tr><td valign="top">$public_must_be_enabled</td>
  <td>
      Specifies if Public Access must be enabled in System Settings
      for this page to be viewed.
      <br />Default setting: false
  </td></tr>

<tr><td valign="top">$display_link</td>
  <td>
      Specifies if events should have a link to the URL
      within WebCalendar to view the event.
      <br />Default setting: true
  </td></tr>

<tr><td valign="top">$link_target</td>
  <td>
      Specifies the name of the window that be used for
      the link target.
      <br />Default setting: _top
  </td></tr>

<tr><td valign="top">$numDays</td>
  <td>
      Specifies how many days of events should be listed.
      <br />Can override this by passing "num" in within the URL
           with "upcoming.php?num=60"
      <br />Default setting: 30
  </td></tr>

<tr><td valign="top">$maxEvents</td>
  <td>
      Specifies the maximum number of events to list.
      <br />Default setting: 10
  </td></tr>

<tr><td valign="top">$username</td>
  <td>
      The login of the calendar to display upcoming events for.
      If you want to see upcoming events for user login "joe",
      then you would change this to "joe".
      <br />Default setting: __public__ (The public calendar)
  </td></tr>

<tr><td valign="top">$allow_user_override</td>
  <td>
      Specifies whether the calendar user can be specified in the URL
      (in which case the $username setting will be ignored) using
      a URL like "upcoming.php?user=joe".
      <br />Default setting: true
  </td></tr>

<tr><td valign="top">$load_layers</td>
  <td>
      Specifies if the calendar user's layers should also be
      included in the upcoming events.
      <br />Note: Layers must be enabled in the user's preferences.
      <br />Default setting: true
  </td></tr>

<tr><td valign="top">$cat_id</td>
  <td>
      Specifies a category id to filter events on.
      <br />Note: Categories must be enabled in System Settings.
      <br />Default setting: (empty)
  </td></tr>

</table>

<p>Below is an example of how you would include <tt>upcoming.php</tt>
   in a simple HTML page.</p>
<pre>
&lt;html&gt;&lt;head&gt;&lt;title&gt;ACME Home Page&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;Welcome to the ACME Home Page&lt;/h1&gt;
&lt;h2&gt;News&lt;/h2&gt;
&lt;p&gt;No news....&lt;/p&gt;
&lt;h2&gt;Upcoming Events&lt;/h2&gt;
&lt;iframe src="upcoming.php" width="400" height="400" name="califrame"&gt;&lt;/iframe&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

<p><span class="tip">TIP</span>
  The <a href="http://www.w3schools.com/tags/tag_iframe.asp"
  target="_blank">W3 Schools</a> site provides documentation
  about the different options that you can use
  with the <tt>iframe</tt> tag.</p>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appendixE"></a>
<h2>Appendix E: How To Configure for LDAP</h2>

<p>Configuring WebCalendar to use an existing LDAP directory is fairly
simple. It is know to work with OpenLDAP and Novell Edirectory and
should work with other systems as well.
<br />
<span class="note">Note:</span>
If you use LDAP, the group functionality of WebCalendar does not yet work.</p>

<p>To configure WebCalendar to use LDAP, do the following:</p>
<ol>
 <li>Configure <tt>settings.php</tt></li>
 <li>Configure <tt>includes/user-ldap.php</tt></li>
</ol>

<p>The first step is to set WebCalendar to use LDAP authentication in
<tt>settings.php</tt>. Instructions on to do this can be found in the
<a href="#appsetup">Application Installation</a> section above.
In summary, the following should be set:<br />
<tt>use_http_auth = false</tt><br />
<tt>user_inc = user-ldap.php</tt><br /></p>

<p>The next step is a little more work and involves editing the
<tt>includes/user-ldap.php</tt> file with a text editor. You will have
to set several configuration variables. If you don't know what to set
the variables to, consult your LDAP system administrator. Documentation
exists for all variables in the file. Finally, users have gotten LDAP
working with OpenLDAP and Novell Edirectory by just changing the
following:</p>

<table border="0" style="margin-left: 20px; margin-right: 20px;">

<tr><td valign="top">$ldap_server</td>
  <td>
      FQDN or IP address of the LDAP server (or localhost).
      <br />ex. 'ldapserver.company.com'
  </td></tr>

<tr><td valign="top">$ldap_base_dn</td>
  <td>
      Specifies the base DN used to search for users
      <br />ex. 'ou=people,dc=company,dc=com' or 'o=context,ou=subcontext'
  </td></tr>

<tr><td valign="top">$ldap_admin_group_name</td>
  <td>
      Specifies a group (complete DN) with admin rights for WebCalendar
      <br />You might have to create one in LDAP
      <br />ex. 'cn=it,ou=group,dc=company,dc=com'
  </td></tr>

</table>

<h3>Using SSL with LDAP</h3>
<p>If the LDAP server will accept connections over SSL, simply add 'ldaps://'
to the beginning of <tt>$ldap_server</tt>.<br />Example: ldaps://ldapserver.company.com</p>

<h3>Using TLS with LDAP</h3>
<p>If the LDAP server is set up to use TLS,  set <tt>$ldap_start_tls = true</tt>.</p>

<h3>Using LDAPv3</h3>
<p>If the LDAP server uses protocol version 3,  set
<tt>$set_ldap_version = true</tt>
and <tt>$ldap_version = '3'</tt>.</p>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />

<a name="appendixF"></a>
<h2>Appendix F: Manual Installation</h2>

<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />
<h3>TODO</h3>

<a name="appendixG"></a>
<h2>Appendix G: Error Codes</h2>
<p>These error codes will be used along with the print_not_auth () function to give an idea of the what the problem might be without displaying site sensitive information.</p>
<p><span class="note">Note:</span> <tt>mode=dev</tt> must be set in includes/settings.php for these error numbers to be displayed</p>
<ul>
<li style="list-style:decimal">ACCESS NOT ENABLED (UAC)</li>
<li style="list-style:decimal">ACCESS ACTIVITY LOG (UAC)</li>
<li style="list-style:decimal">Not Admin</li>
<li style="list-style:decimal">Read Only (setting.php)</li>
<li style="list-style:decimal">Not my event</li>
<li style="list-style:decimal">Can not edit (UAC)</li>
<li style="list-style:decimal">Allow View Others (System Settings)</li>
<li style="list-style:decimal">Can not view (UAC)</li>
<li style="list-style:decimal">Allow Attachment (System Settings)</li>
<li style="list-style:decimal">Allow Comment (System Settings)</li>
<li style="list-style:decimal">REMOTES ENABLED (System Settings)</li>
<li style="list-style:decimal">REPORTS ENABLED (System Settings)</li>
<li style="list-style:decimal">Report user not allowed</li>
<li style="list-style:decimal">Report not yours</li>
<li style="list-style:decimal">ACCESS USER MANAGEMENT (UAC)</li>
<li style="list-style:decimal">Admin can not add user (user.php)</li>
<li style="list-style:decimal">ACCESS ACCOUNT INFO (UAC)</li>
<li style="list-style:decimal">User can not update password (user.php)</li>
<li style="list-style:decimal">FREEBUSY ENABLED (System Settings)</li>
<li style="list-style:decimal">PUBLISH ENABLED (System Settings)</li>
<li style="list-style:decimal">Public must be enabled</li>
<li style="list-style:decimal">Single User (settings.php)</li>
<li style="list-style:decimal">HTTP Auth (settings.php)</li>
<li style="list-style:decimal">Non-User calendar not public</li>
<li style="list-style:decimal">USER PUBLISH ENABLED (System Settings)</li>
<li style="list-style:decimal">ALLOW SELF REGISTRATION (System Settings)</li>
<li style="list-style:decimal">Report ID</li>
<li style="list-style:decimal">RSS ENABLED (System Settings)</li>
<li style="list-style:decimal">USER RSS ENABLED (User preferences)</li>
<li style="list-style:decimal">Categories not enabled (System Settings)</li>
<li style="list-style:decimal">Event deleted for this user</li>
<li style="list-style:decimal">User not participant</li>
<li style="list-style:decimal">Event status empty</li>
<li style="list-style:decimal">View name empty</li>
<li style="list-style:decimal">PUBLIC ACCESS OTHERS (System Settings)</li>
<li style="list-style:decimal">Invalid IP (blacklist.php)</li>
</ul>
<div class="top"><a href="#" target="_top">↑&nbsp;top</a></div>
<hr />
<p>
 <a href="http://validator.w3.org/check?uri=referer"><img
  src="http://www.w3.org/Icons/valid-xhtml10"
  alt="Valid XHTML 1.0!" class="valid" /></a></p>
</body>
</html>

Added docs/newwin.gif.

cannot compute difference between binary files

Added edit_entry.php.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
<?php
/* $Id: edit_entry.php,v 1.203.2.13 2012/02/28 02:49:39 cknudsen Exp $
 *
 * Description:
 * Presents page to edit/add an event/task/journal
 *
 * Notes:
 * A SysAdmin can enable HTML for event full descriptions. If one of the
 * supported HTML edit widgets is also installed, users can use WYSIWYG editing.
 * See the WebCalendar page at
 * http://www.k5n.us/webcalendar.php?topic=Add-Ons
 * for download and install instructions for these packages.
 */
include_once 'includes/init.php';

/* Generate HTML for a time selection for use in a form.
 *
 * @param string $prefix Prefix to use in front of form element names
 * @param string $time   Currently selected time in HHMMSS
 * @param bool $trigger  Add onchange event trigger that
 *                       calls javascript function $prefix_timechanged ()
 *
 * @return string HTML for the selection box
 */
function time_selection ( $prefix, $time = '', $trigger = false ) {
  global $checked, $ENTRY_SLOTS, $selected, $TIME_FORMAT, $WORK_DAY_START_HOUR;

  $amsel = $pmsel = $ret = '';
  $trigger_str = ( $trigger ? 'onchange="' . $prefix . 'timechanged() ' : '' );

  if ( ! isset ( $time ) && $time != 0 ) {
    $hour = $WORK_DAY_START_HOUR;
    $minute = 0;
  } else {
    $hour = floor ( $time / 10000 );
    $minute = ( ( $time / 100 ) % 100 ) % 60;
  }
  if ( $TIME_FORMAT == '12' ) {
    $maxhour = 12;
    if ( $hour < 12 || $hour == 24 )
      $amsel = $checked;
    else
      $pmsel = $checked;

    $hour %= 12;
    if ( $hour == 0 )
      $hour = 12;
  } else {
    $maxhour = 24;
    $hour = sprintf ( "%02d", $hour );
  }
  $minute = sprintf ( "%02d", $minute );
  $ret .= '
            <select ' . 'name="' . $prefix . 'hour" id="' . $prefix . 'hour" '
   . $trigger_str . '>';
  for ( $i = 0; $i < $maxhour; $i++ ) {
    $ihour = ( $TIME_FORMAT == '24' ? sprintf ( "%02d", $i ) : $i );
    if ( $i == 0 && $TIME_FORMAT == '12' )
      $ihour = 12;

    $ret .= '
              <option value="' . "$i\"" . ( $ihour == $hour ? $selected : '' )
     . ">$ihour" . '</option>';
  }
  $ret .= '
            </select>:
            <select ' . 'name="' . $prefix . 'minute" id="' . $prefix
   . 'minute" ' . $trigger_str . '>';
  // We use $TIME_SLOTS to populate the minutes pulldown.
  $found = false;
  for ( $i = 0; $i < 60; ) {
    $imin = sprintf ( "%02d", $i );
    $isselected = '';
    if ( $imin == $minute ) {
      $found = true;
      $isselected = $selected;
    }
    $ret .= '
              <option value="' . "$i\"$isselected>$imin" . '</option>';
    $i += ( 1440 / $ENTRY_SLOTS );
  }
  // We'll add an option with the exact time if not found above.
  return $ret . ( $found ? '' : '
              <option value="' . "$minute\" $selected>$minute" . '</option>' ) . '
            </select>' . ( $TIME_FORMAT == '12' ? '
            <label><input type="radio" name="' . $prefix . 'ampm" id="'
     . $prefix . 'ampmA" value="0" ' . $amsel . ' />&nbsp;' . translate ( 'am' )
     . '</label>
            <label><input type="radio" name="' . $prefix . 'ampm" id="'
     . $prefix . 'ampmP" value="12" ' . $pmsel . ' />&nbsp;' . translate ( 'pm' )
     . '</label>' : '
            <input type="hidden" name="' . $prefix . 'ampm" value="0" />' );
}

$daysStr = translate ( 'days' );
$hoursStr = translate ( 'hours' );
$minutStr = translate ( 'minutes' );
$saveStr = translate ( 'Save' );

load_user_categories ();

// Default for using tabs is enabled.
if ( empty ( $EVENT_EDIT_TABS ) )
  $EVENT_EDIT_TABS = 'Y'; // default

$useTabs = ( $EVENT_EDIT_TABS == 'Y' );
// Make sure this is not a read-only calendar.
$can_edit = false;
$others_complete = 'yes';
$checked = ' checked="checked"';
$selected = ' selected="selected"';

// Public access can only add events, not edit.
if ( empty ( $login ) || ( $login == '__public__' && $id > 0 ) )
  $id = 0;

$eType = getGetValue ( 'eType' );
if ( empty ( $eType ) )
  $eType = 'event';

$copy = getValue ( 'copy', '[01]' );
$date = getValue ( 'date', '-?[0-9]+' );
$day = getValue ( 'day', '-?[0-9]+' );
$month = getValue ( 'month', '-?[0-9]+' );
$year = getValue ( 'year', '-?[0-9]+' );

if ( empty ( $date ) && empty ( $month ) ) {
  if ( empty ( $year ) )
    $year = date ( 'Y' );

  $month = date ( 'm' );

  if ( empty ( $day ) )
    $day = date ( 'd' );

  $date = sprintf ( "%04d%02d%02d", $year, $month, $day );
}

$BodyX = 'onload="onLoad();"';
$INC = array ( 'js/edit_entry.php/false/' . $user, 'js/visible.php' );
$textareasize = '15';

// Can we use HTMLArea or FCKEditor? (Relax! That's the authors initials.)
// Note: HTMLArea has been discontinued, so FCKEditor is preferred.
$use_fckeditor = $use_htmlarea = false;

if ( $ALLOW_HTML_DESCRIPTION == 'Y' ) {
  // Allow HTML in description.
  // If they have installed an HTML edit widget, make use of it.
  if ( file_exists ( 'includes/FCKeditor-2.0/fckeditor.js' ) &&
      file_exists ( 'includes/FCKeditor-2.0/fckconfig.js' ) ) {
    $textareasize = '20';
    $use_fckeditor = true;
  } else
  if ( file_exists ( 'includes/htmlarea/htmlarea.php' ) ) {
    $BodyX = 'onload="onLoad();initEditor();';
    $INC[] = 'htmlarea/core.php/true';
    $INC[] = 'htmlarea/htmlarea.php/true';
    $use_htmlarea = true;
  }
}

$byday = $bymonth = $bymonthday = $bysetpos = $participants = array ();
$exceptions = $inclusions = $reminder = array ();
$byweekno = $byyearday = $catList = $catNames = $external_users = $rpt_count = '';

$create_by = $login;

//This is the default per RFC2445
//We could override it and use $byday_names[$WEEK_START]
$wkst = 'MO';

$real_user = ( ( ! empty ( $user ) && strlen ( $user ) ) &&
  ( $is_assistant || $is_admin ) ) ? $user : $login;

print_header ( $INC, '', $BodyX, false, false, false, true );

ob_start ();

if ( $readonly == 'Y' || $is_nonuser )
  $can_edit = false;
else
if ( ! empty ( $id ) && $id > 0 ) {
  // First see who has access to edit this entry.
  if ( $is_admin )
    $can_edit = true;

  $res = dbi_execute ( 'SELECT cal_create_by, cal_date, cal_time, cal_mod_date,
    cal_mod_time, cal_duration, cal_priority, cal_type, cal_access, cal_name,
    cal_description, cal_group_id, cal_location, cal_due_date, cal_due_time,
    cal_completed, cal_url FROM webcal_entry WHERE cal_id = ?', array ( $id ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    // If current user is creator of event, then they can edit.
    if ( $row[0] == $login )
      $can_edit = true;

    $cal_date = ( ! empty ( $override ) && ! empty ( $date )
      ? $date // Leave $cal_date to what was set in URL with date=YYYYMMDD.
      : $row[1] );

    $create_by = $row[0];
    if ( ( $user == $create_by ) && ( $is_assistant || $is_nonuser_admin ) )
      $can_edit = true;

    $cal_time = sprintf ( "%06d", $row[2] );
    $due_date = $row[13];
    $due_time = $row[14];

    $calTS = date_to_epoch ( $cal_date . $cal_time );
    // Don't adjust for All Day entries.
    if ( $cal_time > 0 || ( $cal_time == 0 && $row[5] != 1440 ) ) {
      $cal_date = date ( 'Ymd', $calTS );
      $cal_time = date ( 'His', $calTS );
    }
    $hour = floor ( $cal_time / 10000 );
    $minute = ( $cal_time / 100 ) % 100;

    $dueTS = date_to_epoch ( $due_date . $due_time );
    $due_date = date ( 'Ymd', $dueTS );
    $due_time = date ( 'His', $dueTS );
    $due_hour = floor ( $due_time / 10000 );
    $due_minute = ( $due_time / 100 ) % 100;

    $priority = $row[6];
    $type = $row[7];
    $access = $row[8];
    $name = $row[9];
    $description = $row[10];
    $parent = $row[11];
    $location = $row[12];
    $completed = ( empty ( $row[15] ) ? date ( 'Ymd' ) : $row[15] );
    $cal_url = $row[16];

    // What kind of entry are we dealing with?
    if ( strpos ( 'EM', $type ) !== false )
      $eType = 'event';
    elseif ( strpos ( 'JO', $type ) !== false )
      $eType = 'journal';
    elseif ( strpos ( 'NT', $type ) !== false )
      $eType = 'task';

    // Public access has no access to tasks.
    // translate ( 'You are not authorized to edit this task' )
    if ( $login == '__public__' && $eType == 'task' )
      echo str_replace ( 'XXX', translate ( 'task' ),
        translate ( 'You are not authorized to edit this XXX.' ) );

    // Check UAC.
    if ( access_is_enabled () )
      $can_edit =
      access_user_calendar ( 'edit', $create_by, $login, $type, $access );

    $day = $cal_date % 100;
    $month = ( $cal_date / 100 ) % 100;
    $year = intval ( $cal_date / 10000 );

    $time = $row[2];

    if ( $time >= 0 )
      $duration = $row[5];
    else {
      $duration = '';
      $hour = -1;
    }

    // Check for repeating event info...
    // but not if we're overriding a single entry of an already repeating event...
    // confusing, eh?
    if ( ! empty ( $override ) ) {
      $rpt_end = 0;
      $rpt_end_date = $cal_date;
      $rpt_freq = 1;
      $rpt_type = 'none';
    } else {
      $res = dbi_execute ( 'SELECT cal_id, cal_type, cal_end, cal_endtime,
        cal_frequency, cal_byday, cal_bymonth, cal_bymonthday, cal_bysetpos,
        cal_byweekno, cal_byyearday, cal_wkst, cal_count
        FROM webcal_entry_repeats WHERE cal_id = ?', array ( $id ) );
      if ( $res ) {
        if ( $row = dbi_fetch_row ( $res ) ) {
          $rpt_type = $row[1];
          $rpt_end = ( $row[2] > 0 ? date_to_epoch ( $row[2] . $row[3] ) : 0 );

          if ( empty ( $row[2] ) ) {
            $rpt_end_date = $cal_date;
            $rpt_end_time = $cal_time;
          } else {
            $rpt_endTS = date_to_epoch ( $row[2] . $row[3] );
            $rpt_end_date = date ( 'Ymd', $rpt_endTS );
            $rpt_end_time = date ( 'His', $rpt_endTS );
          }
          $rpt_freq = $row[4];
          if ( ! empty ( $row[5] ) )
            $byday = explode ( ',', $row[5] );

          $bydayStr = $row[5];
          if ( ! empty ( $row[6] ) )
            $bymonth = explode ( ',', $row[6] );

          if ( ! empty ( $row[7] ) )
            $bymonthday = explode ( ',', $row[7] );

          $bymonthdayStr = $row[7];
          if ( ! empty ( $row[8] ) )
            $bysetpos = explode ( ',', $row[8] );

          $bysetposStr = $row[8];
          $byweekno = $row[9];
          $byyearday = $row[10];
          $wkst = $row[11];
          $rpt_count = $row[12];

          // Check to see if Weekends Only is applicable.
          $weekdays_only = ( $rpt_type == 'daily' && $byday == 'MO,TU,WE,TH,FR' );
        }
        dbi_free_result ( $res );
      }
    }

    $res = dbi_execute ( 'SELECT cal_login, cal_percent, cal_status
      FROM webcal_entry_user WHERE cal_id = ?', array ( $id ) );
    if ( $res ) {
      while ( $row = dbi_fetch_row ( $res ) ) {
        $overall_percent[] = $row;
        if ( $login == $row[0] || ( $is_admin && $user == $row[0] ) ) {
          $task_percent = $row[1];
          $task_status = $row[2];
        }
      }
      dbi_free_result ( $res );
    }

    // Determine if Expert mode needs to be set.
    $expert_mode = ( count ( $byday ) || count ( $bymonth ) ||
      count ( $bymonthday ) || count ( $bysetpos ) ||
      isset ( $byweekno ) || isset ( $byyearday ) || isset ( $rpt_count ) );

    // Get Repeat Exceptions.
    $res = dbi_execute ( 'SELECT cal_date, cal_exdate
      FROM webcal_entry_repeats_not WHERE cal_id = ?', array ( $id ) );
    if ( $res ) {
      while ( $row = dbi_fetch_row ( $res ) ) {
        if ( $row[1] == 1 )
          $exceptions[] = $row[0];
        else
          $inclusions[] = $row[0];
      }
      dbi_free_result ( $res );
    }
  }
  if ( $CATEGORIES_ENABLED == 'Y' ) {
    $catById = get_categories_by_id ( $id, $real_user, true );
    if ( ! empty ( $catById ) ) {
      $catNames = implode ( ', ', $catById );
      $catList = implode ( ',', array_keys ( $catById ) );
    }
  } //end CATEGORIES_ENABLED test

  // Get reminders.
  $reminder = getReminders ( $id );
  $reminder_offset = ( empty ( $reminder ) ? 0 : $reminder['offset'] );
    
    $rem_status = ( count ( $reminder ));
  $rem_use_date = ( ! empty ( $reminder['date'] ) );

  // Get participants.
  $res = dbi_execute ( 'SELECT cal_login, cal_status FROM webcal_entry_user WHERE cal_id = ?
    AND cal_status IN ( \'A\', \'W\' )', array ( $id ) );
  if ( $res ) {
    while ( $row = dbi_fetch_row ( $res ) ) {
      $participants[$row[0]] = 1;
      $selectedStatus[$row[0]] = $row[1];
    }
    dbi_free_result ( $res );
  }
  // Not allowed for tasks or journals.
  if ( $eType == 'event' && !
    empty ( $ALLOW_EXTERNAL_USERS ) && $ALLOW_EXTERNAL_USERS == 'Y' )
    $external_users = event_get_external_users ( $id );
} else {
  // ##########   New entry   ################
  $id = 0; // To avoid warnings below about use of undefined var.

  // We'll use $WORK_DAY_START_HOUR and $WORK_DAY_END_HOUR
  // as our starting and due times.
  $cal_time = $WORK_DAY_START_HOUR . '0000';
  $completed = '';
  $due_hour = $WORK_DAY_END_HOUR;
  $due_minute = $task_percent = 0;
  $due_time = $WORK_DAY_END_HOUR . '0000';
  $overall_percent = array ();

  // Get category if passed in URL as cat_id.
  $cat_id = getValue ( 'cat_id', '-?[0-9,\-]*', true );
  if ( ! empty ( $cat_id ) ) {
    $res = dbi_execute ( 'SELECT cat_name FROM webcal_categories
      WHERE cat_id = ? AND ( cat_owner = ? OR cat_owner IS NULL )',
      array ( $cat_id, $real_user ) );
    if ( $res ) {
      $row = dbi_fetch_row ( $res );
      $catNames = $row[0];
      $catList = $cat_id;
    }
  }

  // Reminder settings.
  $reminder_offset = ( $REMINDER_WITH_DATE == 'N' ? $REMINDER_OFFSET : 0 );

    $rem_status = ( $REMINDER_DEFAULT == 'Y' );
  $rem_use_date = ( $reminder_offset == 0 && $REMINDER_WITH_DATE == 'Y' );
            
  if ( $eType == 'task' )
    $hour = $WORK_DAY_START_HOUR;

  // Anything other then testing for strlen breaks either hour=0 or no hour in URL.
  if ( strlen ( $hour ) )
    $time = $hour * 100;
  else
    $hour = $time = -1;

  if ( ! empty ( $defusers ) ) {
    $tmp_ar = explode ( ',', $defusers );
    for ( $i = 0, $cnt = count ( $tmp_ar ); $i < $cnt; $i++ ) {
      $participants[$tmp_ar[$i]] = 1;
    }
  }

  //Add the logged in user if none other supplied
  if ( count ( $participants )  == 0 )
    $participants[$login] = 1;

  if ( $readonly == 'N' ) {
    // Is public allowed to add events?
    if ( $login == '__public__'  && $PUBLIC_ACCESS_CAN_ADD != 'Y' )
        $can_edit = false;
    else
      $can_edit = true;
  }
}
$dateYmd = date ( 'Ymd' );
$thisday = $day;
$thismonth = $month;
$thisyear = $year;
if ( empty ( $rpt_type ) || ! $rpt_type )
  $rpt_type = 'none';

// Avoid error for using undefined vars.
if ( ! isset ( $hour ) && $hour != 0 )
  $hour = -1;
else
if ( isset ( $hour ) && $hour >= 0 )
  $cal_time = ( $hour * 10000 ) + ( isset ( $minute ) ? $minute * 100 : 0 );

if ( empty ( $access ) )
  $access = '';

if ( empty ( $cal_url ) )
  $cal_url = '';

if ( empty ( $description ) || $description == '<br />' )
  $description = '';

if ( empty ( $duration ) )
  $duration = 0;

if ( $duration == 1440 && $time == 0 ) {
  $duration = $hour = $minute = '';
  $allday = 'Y';
} else
  $allday = 'N';

if ( empty ( $location ) )
  $location = '';

if ( empty ( $name ) )
  $name = '';

if ( empty ( $priority ) )
  $priority = 5;

if ( empty ( $rpt_end_date ) )
  $rpt_end_date = 0;

if ( empty ( $rpt_end_time ) )
  $rpt_end_time = 0;

if ( empty ( $rpt_freq ) )
  $rpt_freq = 0;

if ( empty ( $cal_date ) ) {
  $cal_date = ( ! empty ( $date ) && $eType != 'task' ? $date : $dateYmd );

  if ( empty ( $due_date ) )
    $due_date = $dateYmd;
}
if ( empty ( $thisyear ) )
  $thisdate = $dateYmd;
else {
  $thisdate = sprintf ( "%04d%02d%02d", $thisyear,
    empty ( $thismonth ) ? date ( 'm' ) : $thismonth,
    empty ( $thisday ) ? date ( 'd' ) : $thisday );
}

if ( empty ( $cal_date ) || ! $cal_date )
  $cal_date = $thisdate;

if ( empty ( $due_date ) || ! $due_date )
  $due_date = $thisdate;

// Setup to display user's timezone difference if Admin or Assistant.
// Even though event is stored in GMT,
// an Assistant may need to know that the boss is in a different Timezone.
if ( $is_assistant || $is_admin && ! empty ( $user ) ) {
  $tz_offset = date ( 'Z', date_to_epoch ( $cal_date . $cal_time ) );
  $user_TIMEZONE = get_pref_setting ( $user, 'TIMEZONE' );
  set_env ( 'TZ', $user_TIMEZONE );
  $user_tz_offset = date ( 'Z', date_to_epoch ( $cal_date . $cal_time ) );
  if ( $tz_offset != $user_tz_offset ) { // Different TZ_Offset.
    user_load_variables ( $user, 'temp' );
    $tz_diff = ( $user_tz_offset - $tz_offset ) / 3600;
    $abs_diff = abs ( $tz_diff );
    // translate ( 'is in a different timezone than you are. Currently' )
    // translate ( 'hour ahead of you' ) translate ( 'hour behind you' )
    // translate ( 'hours ahead of you' ) translate ( 'hours behind you' )
    // translate ( 'XXX is in a different timezone (ahead)' )
    // translate ( 'XXX is in a different timezone (behind)' )
    // Line breaks in translates below are to bypass update_translation.pl.
    $TZ_notice = str_replace ( 'XXX',
      array ( $tempfullname,
        // TODO show hh:mm instead of abs.
        $abs_diff . ' ' . translate ( 'hour'
           . ( $abs_diff == 1 ? '' : 's' ) ),
        translate ( 'Time entered here is based on your Timezone.' ) ),
      translate ( 'XXX is in a different timezone ('
         . ( $tz_diff > 0 ? 'ahead)' : 'behind)' ) ) );
  }
  // Return to $login TIMEZONE.
  set_env ( 'TZ', $TIMEZONE );
}

$eType_label = ' ( ' . translate ( $eType ) . ' )';

echo '
    <h2>' . ( $id ? translate ( 'Edit Entry' ) : translate ( 'Add Entry' ) )
 . $eType_label . '&nbsp;<img src="images/help.gif" alt="' . translate ( 'Help' )
 . '" class="help" onclick="window.open( \'help_edit_entry.php'
 . ( empty ( $id ) ? '?add=1' : '' )
 . '\', \'cal_help\', \'dependent,menubar,scrollbars,height=400,width=400,'
 . 'innerHeight=420,outerWidth=420\' );" /></h2>';

if ( $can_edit ) {
  $tabs_ar = array ( 'details', translate ( 'Details' ) );
  if ( $DISABLE_PARTICIPANTS_FIELD != 'Y' ) {
    $tabs_ar[] = 'participants';
    $tabs_ar[] = translate ( 'Participants' );
  }
  if ( $DISABLE_REPEATING_FIELD != 'Y' ) {
    $tabs_ar[] = 'pete';
    $tabs_ar[] = translate ( 'Repeat' );
  }
  if ( $DISABLE_REMINDER_FIELD != 'Y' ) {
    $tabs_ar[] = 'reminder';
    $tabs_ar[] = translate ( 'Reminders' );
  }

  $tabs = '';
  for ( $i = 0, $cnt = count ( $tabs_ar ); $i < $cnt; $i++ ) {
    $tabs .= '
        <span class="tab'
     . ( $i > 0 ? 'bak' : 'for' )
     . '" id="tab_' . $tabs_ar[$i]
     . '"><a href="#tab' . $tabs_ar[$i] . '" onclick="return showTab( \''
     . $tabs_ar[$i] . '\' )">' . $tabs_ar[++$i] . '</a></span>';
  }
  echo '
    <form action="edit_entry_handler.php" method="post" name="editentryform" '
   . 'id="editentryform">
      <input type="hidden" name="eType" value="' . $eType . '" />'
   . ( ! empty ( $id ) && ( empty ( $copy ) || $copy != '1' ) ? '
      <input type="hidden" name="cal_id" value="' . $id . '" />' : '' )
  /* We need an additional hidden input field. */ . '
      <input type="hidden" name="entry_changed" value="" />'
  // Are we overriding an entry from a repeating event...
  . ( empty ( $override ) ? '' : '
      <input type="hidden" name="override" value="1" />
      <input type="hidden" name="override_date" value="' . $cal_date . '" />' )
  // If assistant, need to remember boss = user.
  . ( $is_assistant || $is_nonuser_admin || ! empty ( $user ) ? '
      <input type="hidden" name="user" value="' . $user . '" />' : '' )
  // If has cal_group_id was set, need to set parent = $parent.
  . ( empty ( $parent ) ? '' : '
      <input type="hidden" name="parent" value="' . $parent . '" />' ) . '

<!-- TABS -->' . ( $useTabs ? '
      <div id="tabs">' . $tabs . '
      </div>' : '' ) . '

<!-- TABS BODY -->' . ( $useTabs ? '
      <div id="tabscontent">
<!-- DETAILS -->
        <a name="tabdetails"></a>
        <div id="tabscontent_details">' : '
      <fieldset>
        <legend>' . translate ( 'Details' ) . '</legend>' ) . '
          <table border="0" summary="">
            <tr>
              <td style="width:14%;" class="tooltip" title="'
   . tooltip ( 'brief-description-help' ) . '"><label for="entry_brief">'
   . translate ( 'Brief Description' ) . ':</label></td>
              <td colspan="2"><input type="text" name="name" id="entry_brief" '
   . 'size="25" value="' . htmlspecialchars ( $name ) . '" /></td>
            </tr>
            <tr>
              <td class="tooltip aligntop" title="'
   . tooltip ( 'full-description-help' ) . '"><label for="entry_full">'
   . translate ( 'Full Description' ) . ':</label></td>
              <td><textarea name="description" id="entry_full" rows="'
   . $textareasize . '" cols="50"' . '>' . htmlspecialchars ( $description )
   . '</textarea></td>' . ( $use_fckeditor || $use_htmlarea ? '
            </tr>
            <tr>
              <td colspan="2"' : '
              <td' ) . ' class="aligntop">'
   . ( ! empty ( $categories ) || $DISABLE_ACCESS_FIELD != 'Y' ||
    ( $DISABLE_PRIORITY_FIELD != 'Y' )
    /* New table for extra fields. */ ? '
                <table border="0" width="90%" summary="">' : '' )
   . ( $DISABLE_ACCESS_FIELD != 'Y' ? '
                  <tr>
                    <td class="tooltip" title="' . tooltip ( 'access-help' )
     . '"><label for="entry_access">' . translate ( 'Access' ) . ':</label></td>
                    <td width="80%">
                      <select name="access" id="entry_access">
                        <option value="P"' . ( $access == 'P' || !
      strlen ( $access ) ? $selected : '' ) . '>' . translate ( 'Public' )
     . '</option>
                        <option value="R"' . ( $access == 'R' ? $selected : '' )
     . '>' . translate ( 'Private' ) . '</option>
                        <option value="C"' . ( $access == 'C' ? $selected : '' )
     . '>' . translate ( 'Confidential' ) . '</option>
                      </select>
                    </td>
                  </tr>' : '' );

  if ( $DISABLE_PRIORITY_FIELD != 'Y' ) {
    echo '
                  <tr>
                    <td class="tooltip" title="' . tooltip ( 'priority-help' )
     . '"><label for="entry_prio">' . translate ( 'Priority' )
     . ':&nbsp;</label></td>
                    <td>
                      <select name="priority" id="entry_prio">';
    $pri = array ( '',
      translate ( 'High' ),
      translate ( 'Medium' ),
      translate ( 'Low' ) );

    for ( $i = 1; $i <= 9; $i++ ) {
      echo '
                        <option value="' . $i . '"'
       . ( $priority == $i ? $selected : '' )
       . '>' . $i . '-' . $pri[ceil ( $i / 3 )] . '</option>';
    }
    echo '
                      </select>
                    </td>
                  </tr>';
  }
  echo ( ! empty ( $categories ) && $CATEGORIES_ENABLED == 'Y' ? '
                  <tr>
                    <td class="tooltip" title="' . tooltip ( 'category-help' )
     . '" valign="top">
                      <label for="entry_categories">' . translate ( 'Category' )
     . ':<br /></label>
                      <input type="button" value="' . translate ( 'Edit' )
     . '" onclick="editCats( event )" />
                    </td>
                    <td valign="top">
                      <input readonly="readonly" type="text" name="catnames" '
     . 'id="entry_categories" value="' . $catNames
     . '" size="30" onclick="editCats( event )"/>
                      <input type="hidden" name="cat_id" value="' . $catList
     . '" />
                    </td>
                  </tr>' : '' )
   . ( ! empty ( $categories ) || $DISABLE_ACCESS_FIELD != 'Y' ||
    ( $DISABLE_PRIORITY_FIELD != 'Y' ) ? '
                </table>' : '' );

  if ( $eType == 'task' ) { // Only for tasks.
    $completed_visible = ( strlen ( $completed ) ? 'visible' : 'hidden' );
    echo '<br />
                <table border="0" summary="">
                  <tr id="completed">
                    <td class="tooltip" title="' . tooltip ( 'completed-help' )
     . '"><label for="task_percent">' . translate ( 'Date Completed' )
     . ':&nbsp;</label></td>
                    <td>' . date_selection ( 'completed_', $completed ) . '</td>
                  </tr>
                  <tr>
                    <td class="tooltip" title="' . tooltip ( 'percent-help' )
     . '"><label for="task_percent">' . translate ( 'Percent Complete' )
     . ':&nbsp;</label></td>
                    <td>
                      <select name="percent" id="task_percent" '
     . 'onchange="completed_handler()">';
    for ( $i = 0; $i < 101; $i += 10 ) {
      echo '
                        <option value="' . "$i\" "
       . ( $task_percent == $i ? $selected : '' )
       . '>' . $i . '</option>';
    }
    echo '
                      </select>
                    </td>
                  </tr>';

    if ( ! empty ( $overall_percent ) ) {
      echo '
                  <tr>
                    <td colspan="2">
                      <table width="100%" border="0" cellpadding="2" '
       . 'cellspacing="5" summary="">
                        <tr>
                          <td colspan="2">' . translate ( 'All Percentages' )
       . '</td>
                        </tr>';
      $others_complete = 'yes';
      for ( $i = 0, $cnt = count ( $overall_percent ); $i < $cnt; $i++ ) {
        user_load_variables ( $overall_percent[$i][0], 'percent' );
        echo '
                        <tr>
                          <td>' . $percentfullname . '</td>
                          <td>' . $overall_percent[$i][1] . '</td>
                        </tr>';
        if ( $overall_percent[$i][0] != $real_user &&
          $overall_percent[$i][1] < 100 )
          $others_complete = 'no';
      }
      echo '
                      </table>';
    }
    echo '
                    </td>
                  </tr>
                </table>
                <input type="hidden" name="others_complete" value="'
     . $others_complete . '" />';
  } //end tasks only

  echo '
              </td>
            </tr>' . ( $DISABLE_LOCATION_FIELD != 'Y' ? '
            <tr>
              <td class="tooltip" title="' . tooltip ( 'location-help' )
     . '"><label for="entry_location">' . translate ( 'Location' )
     . ':</label></td>
              <td colspan="2"><input type="text" name="location" '
     . 'id="entry_location" size="55" value="' . htmlspecialchars ( $location )
     . '" /></td>
            </tr>' : '' ) . ( $DISABLE_URL_FIELD != 'Y' ? '
            <tr>
              <td class="tooltip" title="' . tooltip ( 'url-help' )
     . '"><label for="entry_url">' . translate ( 'URL' ) . ':</label></td>
              <td colspan="2"><input type="text" name="entry_url" id="entry_url" '
     . 'size="100" value="' . htmlspecialchars ( $cal_url ) . '" /></td>
            </tr>' : '' ) . '
            <tr>
              <td class="tooltip" title="' . tooltip ( 'date-help' )
   . '"><label>'
   . ( $eType == 'task' ? translate ( 'Start Date' ) : translate ( 'Date' ) )
   . ':</label></td>
              <td colspan="2">' . date_selection ( '', $cal_date ) . '</td>
            </tr>
            <tr>
              <td';

  if ( $eType != 'task' ) {
    $dur_h = intval ( $duration / 60 );

    echo '>&nbsp;</td>
              <td colspan="2">
                <select name="timetype" onchange="timetype_handler()">
                  <option value="U" '
     . ( $allday != 'Y' && $hour == -1 ? $selected : '' ) . '>'
     . translate ( 'Untimed event' ) . '</option>
                  <option value="T" '
     . ( $allday != 'Y' && $hour >= 0 ? $selected : '' ) . '>'
     . translate ( 'Timed event' ) . '</option>
                  <option value="A" '
     . ( $allday == 'Y' ? $selected : '' ) . '>'
     . translate ( 'All day event' ) . '</option>
                </select>
              </td>
            </tr>' . ( empty ( $TZ_notice ) ? '' : '
            <tr id="timezonenotice">
              <td class="tooltip" title="'
       . tooltip ( 'Time entered here is based on your Timezone.' ) . '">'
       . translate ( 'Timezone Offset' ) . ':</td>
              <td colspan="2">' . $TZ_notice . '</td>
            </tr>' ) . '
            <tr id="timeentrystart" style="visibility:hidden;">
              <td class="tooltip" title="' . tooltip ( 'time-help' ) . '">'
     . translate ( 'Time' ) . ':' . '</td>
              <td colspan="2">' . time_selection ( 'entry_', $cal_time );

    if ( $TIMED_EVT_LEN != 'E' ) {
      echo '
              </td>
            </tr>
            <tr id="timeentryduration" style="visibility:hidden;">
              <td><span class="tooltip" title="' . tooltip ( 'duration-help' )
       . '">' . translate ( 'Duration' ) . ':&nbsp;</span></td>
              <td colspan="2">
                <input type="text" name="duration_h" id="duration_h" size="2" '
       . 'maxlength="2" value="';
      if ( $allday != 'Y' )
        printf ( "%d", $dur_h );

      echo '" />:
                <input type="text" name="duration_m" id="duration_m" size="2" '
       . 'maxlength="2" value="';
      if ( $allday != 'Y' )
        printf ( "%02d", $duration - ( $dur_h * 60 ) );

      echo '" />&nbsp;(<label for="duration_h">' . $hoursStr
       . '</label>: <label for="duration_m">' . $minutStr
       . '</label>)
              </td>
            </tr>';
    } else
      echo '
            <span id="timeentryend" class="tooltip" title="'
       . tooltip ( 'end-time-help' ) . '">&nbsp;-&nbsp;'
       . time_selection ( 'end_',
        ( $id ? add_duration ( $cal_time, $duration ) : $cal_time ) ) . '</span>
          </td>
        </tr>';
  } else { // eType == task
    echo ' class="tooltip" title="' . tooltip ( 'time-help' ) . '">'
     . translate ( 'Start Time' ) . ':</td>
          <td colspan="2">' . time_selection ( 'entry_', $cal_time ) . '</td>
        </tr>
        <tr>
          <td colspan="3">&nbsp;</td>
        </tr>
        <tr>
          <td class="tooltip" title="' . tooltip ( 'date-help' ) . '">'
     . translate ( 'Due Date' ) . ':</td>
          <td colspan="2">' . date_selection ( 'due_', $due_date ) . '</td>
        </tr>
        <tr>
          <td class="tooltip" title="' . tooltip ( 'time-help' ) . '">'
     . translate ( 'Due Time' ) . ':</td>
          <td colspan="2">' . time_selection ( 'due_', $due_time ) . '</td>
        </tr>';
  }

  // Site-specific extra fields (see site_extras.php).
  // load and display any site-specific fields.
  if ( $id > 0 )
    $extras = get_site_extra_fields ( $id );

  $site_extracnt = count ( $site_extras );
  echo '
      </table>' . ( $site_extracnt ? ( ! empty ( $site_extras[0]['FIELDSET'] ) ? '
      <div>
        <fieldset>
          <legend>' . translate ( 'Site Extras' ) . '</legend>' : '' ) . '
          <table summary="">' : '' );

  for ( $i = 0; $i < $site_extracnt; $i++ ) {
    if ( $site_extras[$i] == 'FIELDSET' )
      continue;

    $extra_name = $site_extras[$i][0];
    $extra_descr = $site_extras[$i][1];
    $extra_type = $site_extras[$i][2];
    $extra_arg1 = $site_extras[$i][3];
    $extra_arg2 = $site_extras[$i][4];
    // Default value if needed.
    $defIdx = ( empty ( $extras[$extra_name]['cal_data'] )
      ? $extra_arg2 : $extras[$extra_name]['cal_data'] );

    echo '
            <tr>
              <td class="aligntop bold">'
     . ( $extra_type == EXTRA_MULTILINETEXT ? '<br />' : '' )
     . translate ( $extra_descr ) . ':</td>
              <td>';

    if ( $extra_type == EXTRA_URL )
      echo '
                <input type="text" size="50" name="' . $extra_name . '" value="'
       . ( empty ( $extras[$extra_name]['cal_data'] )
        ? '' : htmlspecialchars ( $extras[$extra_name]['cal_data'] ) ) . '" />';
    elseif ( $extra_type == EXTRA_EMAIL )
      echo '
                <input type="text" size="30" name="' . $extra_name . '" value="'
       . ( empty ( $extras[$extra_name]['cal_data'] )
        ? '' : htmlspecialchars ( $extras[$extra_name]['cal_data'] ) ) . '" />';
    elseif ( $extra_type == EXTRA_DATE )
      echo date_selection ( $extra_name,
        ( empty ( $extras[$extra_name]['cal_date'] )
          ? $cal_date : $extras[$extra_name]['cal_date'] ) );
    elseif ( $extra_type == EXTRA_TEXT ) {
      $size = ( $extra_arg1 > 0 ? $extra_arg1 : 50 );
      echo '
                <input type="text" size="' . $size . '" name="' . $extra_name
       . '" value="' . ( empty ( $extras[$extra_name]['cal_data'] )
        ? '' : htmlspecialchars ( $extras[$extra_name]['cal_data'] ) ) . '" />';
    } elseif ( $extra_type == EXTRA_MULTILINETEXT )
      echo '
                <textarea rows="' . ( $extra_arg2 > 0 ? $extra_arg2 : 5 )
       . '" cols="' . ( $extra_arg1 > 0 ? $extra_arg1 : 50 ) . '" name="'
       . $extra_name . '">' . ( empty ( $extras[$extra_name]['cal_data'] )
        ? '' : htmlspecialchars ( $extras[$extra_name]['cal_data'] ) )
       . '</textarea>';
    elseif ( $extra_type == EXTRA_USER ) {
      // Show list of calendar users...
      echo '
                <select name="' . $extra_name . '">
                  <option value="">None</option>';
      $userlist = get_my_users ( get_my_users );
      $usercnt = count ( $userlist );
      for ( $j = 0; $j < $usercnt; $j++ ) {
        if ( access_is_enabled () && !
            access_user_calendar ( 'view', $userlist[$j]['cal_login'] ) )
          continue; // Cannot view calendar so cannot add to their cal.

        echo '
                  <option value="' . $userlist[$j]['cal_login'] . '"'
         . ( ! empty ( $extras[$extra_name]['cal_data'] ) &&
          ( $userlist[$j]['cal_login'] == $extras[$extra_name]['cal_data'] )
          ? $selected : '' )
         . '>' . $userlist[$j]['cal_fullname'] . '</option>';
      }
      echo '
                </select>';
    } elseif ( $extra_type == EXTRA_SELECTLIST ) {
      // Show custom select list.
      $extraSelectArr = $isMultiple = $multiselect = '';
      if ( is_array ( $extra_arg1 ) ) {
        $extra_arg1cnt = count ( $extra_arg1 );
        if ( $extra_arg2 > 0 ) {
          $multiselect = ' multiple="multiple" size="'
           . min ( $extra_arg2, $extra_arg1cnt ) . '" ';
          $isMultiple = '[]';
          if ( ! empty ( $extras ) )
            $extraSelectArr = explode ( ',', $extras[$extra_name]['cal_data'] );
        }

        echo '
                <select name="' . $extra_name . $isMultiple . '"'
         . $multiselect . '>';
        for ( $j = 0; $j < $extra_arg1cnt; $j++ ) {
          echo '
                  <option value="' . $extra_arg1[$j] . '" ';

          if ( ! empty ( $extras[$extra_name]['cal_data'] ) ) {
            if ( $extra_arg2 == 0 &&
              $extra_arg1[$j] == $extras[$extra_name]['cal_data'] )
              echo $selected;
            else
            if ( $extra_arg2 > 0 &&
              in_array ( $extra_arg1[$j], $extraSelectArr ) )
              echo $selected;
          } else
            echo ( $j == 0 ? $selected : '' );

          echo '>' . $extra_arg1[$j] . '</option>';
        }
      }
      echo '
                  </select>';
    } elseif ( $extra_type == EXTRA_RADIO )
      // Show custom radio selections.
      echo print_radio ( $extra_name, $extra_arg1, '', $defIdx );
    elseif ( $extra_type == EXTRA_CHECKBOX )
      // Show custom checkbox option.
      echo print_checkbox ( array ( $extra_name, $extra_arg1, '', $defIdx ) );

    echo '
                </td>
              </tr>';
  }
  if ( $site_extracnt ) {
    echo '
          </table>' . ( empty ( $site_extras[0]['FIELDSET'] ) ? '' : '
        </fieldset>
      </div>' );
  }
  // end site-specific extra fields

  echo ( $useTabs ? '
    </div>' : '
    </fieldset>' ) . '

<!-- PARTICIPANTS -->' . ( $useTabs ? '
    <a name="tabparticipants"></a>
    <div id="tabscontent_participants">' : '
    <fieldset>
      <legend>' . translate ( 'Participants' ) . '</legend>' ) . '
      <table>';
  // .
  // Only ask for participants if we are multi-user.
  $show_participants = ( $DISABLE_PARTICIPANTS_FIELD != 'Y' );
  if ( $is_admin )
    $show_participants = true;

  if ( $login == '__public__' && $PUBLIC_ACCESS_OTHERS != 'Y' )
    $show_participants = false;

  if ( $single_user == 'N' && $show_participants ) {
    $userlist = get_my_users ( $create_by, 'invite' );
    if ( $NONUSER_ENABLED == 'Y' ) {
      // Include public NUCs.
      $nonusers = get_my_nonusers ( $real_user, false );
      $userlist = ( $NONUSER_AT_TOP == 'Y'
        ? array_merge ( $nonusers, $userlist )
        : array_merge ( $userlist, $nonusers ) );
    }
    $num_users = $size = 0;
    $usercnt = count ( $userlist );
    $users = '';
    for ( $i = 0; $i < $usercnt; $i++ ) {
      $l = $userlist[$i]['cal_login'];
      $size++;
      $users .= '
              <option value="' . $l . '"';
      if ( $id > 0 ) {
        if ( ! empty ( $participants[$l] ) )
          $users .= $selected;
      } else {
        if ( ! empty ( $defusers ) && ! empty ( $participants[$l] ) )
          // Default selection of participants was in the URL.
          $users .= $selected;

        if ( ( $l == $login && ! $is_assistant && ! $is_nonuser_admin ) ||
            ( ! empty ( $user ) && $l == $user ) )
          $users .= $selected;

        if ( $l == '__public__' && !
          empty ( $PUBLIC_ACCESS_DEFAULT_SELECTED ) &&
            $PUBLIC_ACCESS_DEFAULT_SELECTED == 'Y' )
          $users .= $selected;
      }
      $users .= '>' . $userlist[$i]['cal_fullname'] . '</option>';
    }

    if ( $size > 50 )
      $size = 50;
    elseif ( $size > 20 )
      $size = 20;
    elseif ( $size > 5 )
      $size = 5;

    echo '
        <tr title="' . tooltip ( 'participants-help' ) . '">
          <td class="tooltipselect"><label for="entry_part">'
     . translate ( 'Participants' ) . ':</label></td>
          <td>
            <select name="participants[]" id="entry_part" size="' . $size
     . '" multiple="multiple">' . $users . '
            </select>' . ( $GROUPS_ENABLED == 'Y' ? '
            <input type="button" onclick="selectUsers()" value="'
       . translate ( 'Select' ) . '..." />' : '' ) . '
            <input type="button" onclick="showSchedule()" value="'
     . translate ( 'Availability' ) . '..." />
          </td>
        </tr>'
    // External users.
    . ( ! empty ( $ALLOW_EXTERNAL_USERS ) && $ALLOW_EXTERNAL_USERS == 'Y' ? '
        <tr title="' . tooltip ( 'external-participants-help' ) . '">
          <td class="tooltip aligntop"><label for="entry_extpart">'
       . translate ( 'External Participants' ) . ':</label></td>
          <td><textarea name="externalparticipants" id="entry_extpart" rows="5" '
       . 'cols="40">' . $external_users . '</textarea></td>
        </tr>' : '' );
  }
  echo '
      </table>' . ( $useTabs ? '
    </div>' : '
    </fieldset>' ) . '

<!-- REPEATING INFO -->';
  if ( $DISABLE_REPEATING_FIELD != 'Y' ) {
    echo ( $useTabs ? '
    <a name="tabpete"></a>
    <div id="tabscontent_pete">' : '
    <fieldset>
      <legend>' . translate ( 'Repeat' ) . '</legend>' ) . '
      <table border="0" cellspacing="0" cellpadding="3" summary="">
        <tr>
          <td class="tooltip" title="' . tooltip ( 'repeat-type-help' )
     . '"><label for="rpttype">' . translate ( 'Type' ) . ':</label></td>
          <td colspan="2">
            <select name="rpt_type" id="rpttype" '
     . 'onchange="rpttype_handler(); rpttype_weekly()">
              <option value="none"' . ( strcmp ( $rpt_type, 'none' ) == 0
      ? $selected : '' ) . '>' . translate ( 'None' ) . '</option>
              <option value="daily"' . ( strcmp ( $rpt_type, 'daily' ) == 0
      ? $selected : '' ) . '>' . translate ( 'Daily' ) . '</option>
              <option value="weekly"' . ( strcmp ( $rpt_type, 'weekly' ) == 0
      ? $selected : '' ) . '>' . translate ( 'Weekly' ) . '</option>
              <option value="monthlyByDay"'
     . ( strcmp ( $rpt_type, 'monthlyByDay' ) == 0 ? $selected : '' )
     // translate ( 'Monthly' ) translate ( 'by day' ) translate ( 'by date' )
     // translate ( 'by position' )
     . '>' . translate ( 'Monthly (by day)' ) . '</option>
              <option value="monthlyByDate"'
     . ( strcmp ( $rpt_type, 'monthlyByDate' ) == 0 ? $selected : '' )
     . '>' . translate ( 'Monthly (by date)' ) . '</option>
              <option value="monthlyBySetPos"'
     . ( strcmp ( $rpt_type, 'monthlyBySetPos' ) == 0 ? $selected : '' )
     . '>' . translate ( 'Monthly (by position)' ) . '</option>
              <option value="yearly"' . ( strcmp ( $rpt_type, 'yearly' ) == 0
      ? $selected : '' ) . '>' . translate ( 'Yearly' ) . '</option>
              <option value="manual"'
     . ( strcmp ( $rpt_type, 'manual' ) == 0 ? $selected : '' )
     . '>' . translate ( 'Manual' ) . '</option>
            </select>&nbsp;&nbsp;&nbsp;<label id="rpt_mode"><input '
     . 'type="checkbox" name="rptmode" id="rptmode" value="y" '
     . 'onclick="rpttype_handler()" '
     . ( empty ( $expert_mode ) ? '' : $checked )
     . '/>' . translate ( 'Expert Mode' ) . '</label>
          </td>
        </tr>
        <tr id="rptenddate1" style="visibility:hidden;">
          <td class="tooltip" title="' . tooltip ( 'repeat-end-date-help' )
     . '" rowspan="3"><label for="rpt_day">' . translate ( 'Ending' )
     . ':</label></td>
          <td colspan="2" class="boxtop boxright boxleft"><input type="radio" '
     . 'name="rpt_end_use" id="rpt_untilf" value="f" '
     . ( empty ( $rpt_end ) && empty ( $rpt_count ) ? $checked : '' )
     . ' onclick="toggle_until()" /><label for="rpt_untilf">'
     . translate ( 'Forever' ) . '</label></td>
        </tr>
        <tr id="rptenddate2" style="visibility:hidden;">
          <td class="boxleft"><input type="radio" name="rpt_end_use" '
     . 'id="rpt_untilu" value="u" ' . ( empty ( $rpt_end ) ? '' : $checked )
     . ' onclick="toggle_until()" />&nbsp;<label for="rpt_untilu">'
     . translate ( 'Use end date' ) . '</label></td>
          <td class="boxright"><span class="end_day_selection" '
     . 'id="rpt_end_day_select">'
     . date_selection ( 'rpt_', ( $rpt_end_date ? $rpt_end_date : $cal_date ) )
     . '</span><span id="rpt_until_time_date"><br />' . time_selection ( 'rpt_', $rpt_end_time ) . '</span></td>
        </tr>
        <tr id="rptenddate3" style="visibility:hidden;">
          <td class="boxbottom boxleft"><input type="radio" name="rpt_end_use" '
     . 'id="rpt_untilc" value="c" ' . ( empty ( $rpt_count ) ? '' : $checked )
     . ' onclick="toggle_until()" />&nbsp;<label for="rpt_untilc">'
     . translate ( 'Number of times' ) . '</label></td>
          <td class="boxright boxbottom"><input type="text" name="rpt_count" '
     . 'id="rpt_count" size="4" maxlength="4" value="' . $rpt_count . '" /></td>
        </tr>
        <tr id="rptfreq" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-frequency-help' ) . '">
          <td class="tooltip"><label for="entry_freq">'
     . translate ( 'Frequency' ) . ':</label></td>
          <td colspan="2">
            <input type="text" name="rpt_freq" id="entry_freq" size="4" '
     . 'maxlength="4" value="' . $rpt_freq . '" />&nbsp;&nbsp;&nbsp;&nbsp;
            <label id="weekdays_only"><input type="checkbox" '
     . 'name="weekdays_only" value="y" '
     . ( empty ( $weekdays_only ) ? '' : $checked ) . ' />'
     . translate ( 'Weekdays Only' )
     . '</label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <span id="rptwkst">
              <select name="wkst">';
    for ( $i = 0; $i < 7; $i++ ) {
      echo '
                <option value="' . $byday_names[$i] . '" '
                 . ( $wkst ==$byday_names[$i] ? $selected : '' )
       . '>' . translate ( $byday_names[$i] ) . '</option>';
              }
    echo '
              </select>&nbsp;&nbsp;<label for="rptwkst">'
     . translate ( 'Week Start' ) . '</label>
            </span>
          </td>
        </tr>
        <tr>
          <td colspan="4"></td>
        </tr>
        <tr id="rptbydayextended" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-bydayextended-help' ) . '">
          <td class="tooltip"><label>' . translate ( 'ByDay' ) . ':</label></td>
          <td colspan="2" class="boxall">
            <input type="hidden" name="bydayList" value="'
     . ( empty ( $bydayStr ) ? '' : $bydayStr ) . '" />
            <input type="hidden" name="bymonthdayList" value="'
     . ( empty ( $bymonthdayStr ) ? '' : $bymonthdayStr ) . '" />
            <input type="hidden" name="bysetposList" value="'
     . ( empty ( $bysetposStr ) ? '' : $bysetposStr ) . '" />
            <table class="byxxx" cellpadding="2" cellspacing="2" '
     . 'border="1" summary="">
              <tr>
                <td></td>';
    // Display byday extended selection.
    // We use BUTTONS in a triple state configuration, and store the values in
    // a javascript array until form submission. We then set the hidden field
    // bydayList to the string value of the array.
    for ( $rpt_byday_label = $WEEK_START; 
          $rpt_byday_label <= ( $WEEK_START + 6); $rpt_byday_label++ ) {
            $rpt_byday_mod = $rpt_byday_label %7;
            $class = ( is_weekend ( $rpt_byday_mod ) ? ' class="weekend" ' : '' );
      echo '
                <th width="50px"' .$class . '><label>'
       . translate ( $weekday_names[$rpt_byday_mod] ) . '</label></th>';
    }
    echo '
              </tr>
              <tr>
                <th>' . translate ( 'All' ) . '</th>';
    for ( $rpt_byday_single = $WEEK_START; 
          $rpt_byday_single <= ( $WEEK_START + 6); $rpt_byday_single++ ) {
            $rpt_byday_mod = $rpt_byday_single %7;
      echo '
                <td><input type="checkbox" name="bydayAll[]" id="'
       . $byday_names[$rpt_byday_mod] . '" value="'
       . "$byday_names[$rpt_byday_mod]\""
       . ( in_array ( $byday_names[$rpt_byday_mod], $byday ) ? $checked : '' )
       . ' /></td>';
    }
    echo '
              </tr>
              <tr id="rptbydayln" style="visibility:hidden;">';
    for ( $loop_ctr = 1; $loop_ctr < 6; $loop_ctr++ ) {
      echo '
                <th><label>' . $loop_ctr . '/' . ( $loop_ctr - 6 )
       . '</label></th>';
      for ( $rpt_byday = $WEEK_START; 
              $rpt_byday <= ( $WEEK_START + 6); $rpt_byday++ ) {
                $rpt_byday_mod = $rpt_byday %7;
        $buttonvalue = ( in_array ( $loop_ctr
             . $byday_names[$rpt_byday_mod], $byday )
          ? $loop_ctr . translate ( $byday_names[$rpt_byday_mod] )
          : ( in_array ( ( $loop_ctr - 6 ) 
                    . $byday_names[$rpt_byday_mod], $byday )
          ? ( $loop_ctr - 6 )
          . translate ( $byday_names[$rpt_byday_mod] ) : '        ' ) );

        echo '
                <td><input type="button" name="byday" id="_' . $loop_ctr
         . $rpt_byday_mod . '" value="' . $buttonvalue
         . '" onclick="toggle_byday( this )" /></td>';
      }
      echo '
              </tr>';
      if ( $loop_ctr < 5 )
        echo '
              <tr id="rptbydayln' . $loop_ctr . '" style="visibility:hidden;">';
    }
    echo '
            </table>
          </td>
        </tr>
        <tr>
          <td colspan="4"></td>
        </tr>
        <tr id="rptbymonth" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-month-help' ) . '">
          <td class="tooltip">' . translate ( 'ByMonth' ) . ':&nbsp;</td>
          <td colspan="2" class="boxall">'
    /* Display bymonth selection. */ . '
            <table cellpadding="5" cellspacing="0" summary="">
              <tr>';
    for ( $rpt_month = 1; $rpt_month < 13; $rpt_month++ ) {
      echo '
                <td><label><input type="checkbox" name="bymonth[]" value="'
       . $rpt_month . '"' . ( in_array ( $rpt_month, $bymonth ) ? $checked : '' )
       . ' />&nbsp;' . translate (
        date ( 'M', mktime ( 0, 0, 0, $rpt_month, 1 ) ) )
       . '</label></td>' . ( $rpt_month == 6 ? '
              </tr>
              <tr>' : '' );
    }
    echo '
              </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td colspan="4"></td>
        </tr>
        <tr id="rptbysetpos" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-bysetpos-help' ) . '">
          <td class="tooltip" id="BySetPoslabel">' . translate ( 'BySetPos' )
     . ':&nbsp;</td>
          <td colspan="2" class="boxall">'
    /* Display bysetpos selection. */ . '
            <table class="byxxx" cellpadding="2" cellspacing="0" '
     . 'border="1" summary="">
              <tr>
                <td></td>';
    for ( $rpt_bysetpos_label = 1; $rpt_bysetpos_label < 11;
      $rpt_bysetpos_label++ ) {
      echo '
                <th width="37px"><label>' . $rpt_bysetpos_label
       . '</label></th>';
    }
    echo '
              </tr>
              <tr>';
    for ( $loop_ctr = 1; $loop_ctr < 32; $loop_ctr++ ) {
      $buttonvalue = ( in_array ( $loop_ctr, $bysetpos )
        ? ( $loop_ctr ) : ( in_array ( ( $loop_ctr -32 ), $bysetpos )
          ? ( $loop_ctr -32 ) : '      ' ) );
      echo ( $loop_ctr == 1 || $loop_ctr == 11 || $loop_ctr == 21 ? '
                <th><label>' . $loop_ctr . '-' . ( $loop_ctr + 9 )
         . '</label></th>' : '' ) . ( $loop_ctr == 31 ? '
                <th><label>31</label></th>' : '' ) . '
                <td><input type="button" name="bysetpos" id="bysetpos'
       . $loop_ctr . '" value="' . $buttonvalue
       . '" onclick="toggle_bysetpos( this )" /></td>'
       . ( $loop_ctr % 10 == 0 ? '
              </tr>
            <tr>' : '' );
    }
    echo '
            </tr>
          </table>
        </td>
      </tr>
      <tr>
        <td colspan="4"></td>
      </tr>
      <tr id="rptbymonthdayextended" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-bymonthdayextended-help' ) . '">
        <td class="tooltip" id="ByMonthDaylabel">' . translate ( 'ByMonthDay' )
     . ':&nbsp;</td>
        <td colspan="2" class="boxall">'
    /* Display bymonthday extended selection. */ . '
          <table class="byxxx" cellpadding="2" cellspacing="0" '
     . 'border="1" summary="">
            <tr>
              <td></td>';
    for ( $rpt_bymonthday_label = 1; $rpt_bymonthday_label < 11;
      $rpt_bymonthday_label++ ) {
      echo '
              <th width="37px"><label>' . $rpt_bymonthday_label
       . '</label></th>';
    }
    echo '
            </tr>
            <tr>';
    for ( $loop_ctr = 1; $loop_ctr < 32; $loop_ctr++ ) {
      $buttonvalue = ( in_array ( $loop_ctr, $bymonthday )
        ? ( $loop_ctr ) : ( in_array ( ( $loop_ctr -32 ), $bymonthday )
          ? ( $loop_ctr - 32 ) : '      ' ) );
      echo ( $loop_ctr == 1 || $loop_ctr == 11 || $loop_ctr == 21 ? '
            <th><label>' . $loop_ctr . '-' . ( $loop_ctr + 9 )
         . '</label></th>' : '' )
       . ( $loop_ctr == 31 ? '
            <th><label>31</label></th>' : '' ) . '
            <td><input type="button" name="bymonthday" id="bymonthday'
       . $loop_ctr . '" value="' . $buttonvalue
       . '" onclick="toggle_bymonthday( this )" /></td>'
       . ( $loop_ctr % 10 == 0 ? '
          </tr>
          <tr>' : '' );
    }
    echo '
          </tr>
        </table>';

    // Populate Repeat Exceptions data for later use.
    $excepts = '';
    $exceptcnt = count ( $exceptions );
    for ( $i = 0; $i < $exceptcnt; $i++ ) {
      $excepts .= '
                  <option value="-' . $exceptions[$i] . '">-' . $exceptions[$i]
       . '</option>';
    }
    // Populate Repeat Inclusions data for later use
    $includecnt = count ( $inclusions );
    for ( $i = 0; $i < $includecnt; $i++ ) {
      $excepts .= '
                  <option value="+' . $inclusions[$i] . '">+' . $inclusions[$i]
       . '</option>';
    }

    echo '
       </td>
      </tr>
      <tr id="rptbyweekno" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-byweekno-help' ) . '">
        <td class="tooltip">' . translate ( 'ByWeekNo' ) . ':</td>
        <td colspan="2"><input type="text" name="byweekno" id="byweekno" '
     . 'size="50" maxlength="100" value="' . $byweekno . '" /></td>
      </tr>
      <tr id="rptbyyearday" style="visibility:hidden;" title="'
     . tooltip ( 'repeat-byyearday-help' ) . '">
        <td class="tooltip">' . translate ( 'ByYearDay' ) . ':</td>
        <td colspan="2"><input type="text" name="byyearday" id="byyearday" '
     . 'size="50" maxlength="100" value="' . $byyearday . '" /></td>
      </tr>
      <tr id="rptexceptions" style="visibility:visible;" title="'
     . tooltip ( 'repeat-exceptions-help' ) . '">
        <td class="tooltip"><label>' . translate ( 'Exclusions' ) . '/<br />'
     . translate ( 'Inclusions' ) . ':</label></td>
        <td colspan="2" class="boxtop boxright boxbottom boxleft">
          <table border="0" width="250px" summary="">
            <tr>
              <td colspan="2">'
     . date_selection ( 'except_', $rpt_end_date ? $rpt_end_date : $cal_date )
     . '</td>
            </tr>
            <tr>
              <td align="right" valign="top" width="100">
                <label id="select_exceptions_not" style="visibility:'
     . ( empty ( $excepts ) ? 'visible' : 'hidden' ) . ';"></label>
                <select id="select_exceptions" name="exceptions[]" '
     . 'multiple="multiple" style="visibility:'
     . ( empty ( $excepts ) ? 'hidden' : 'visible' )
     . ';" size="4">' . $excepts . '
                </select>
              </td>
              <td valign="top">
                <input align="left" type="button" name="addException" value="'
     . translate ( 'Add Exception' ) . '" onclick="add_exception(0)" /><br />
                <input align="left" type="button" name="addInclusion" value="'
     . translate ( 'Add Inclusion' ) . '" onclick="add_exception(1)" /><br />
                <input align="left" type="button" name="delSelected" value="'
     . translate ( 'Delete Selected' ) . '" onclick="del_selected()" />
              </td>
            </tr>
          </table>
        </td>
      </tr>
    </table>' . ( $useTabs ? '
    </div> <!-- End tabscontent_pete -->' : '
    </fieldset>' );
  }

  echo '

<!-- REMINDER INFO -->';
  if ( $DISABLE_REMINDER_FIELD != 'Y' ) {
    $rem_minutes = $reminder_offset;
    // Will be specified in total minutes.
    $rem_days = intval ( $rem_minutes / 1440 );
    $rem_minutes -= ( $rem_days * 1440 );
    $rem_hours = intval ( $rem_minutes / 60 );
    $rem_minutes -= ( $rem_hours * 60 );

    $rem_before =
    ( empty ( $reminder['before'] ) || $reminder['before'] == 'Y' );
    $rem_related =
    ( empty ( $reminder['related'] ) || $reminder['related'] == 'S' );

    // Reminder Repeats.
    $rem_rep_count =
    ( isset ( $reminder['repeats'] ) ? $reminder['repeats'] : 0 );
    $rem_rep_minutes =
    ( isset ( $reminder['duration'] ) ? $reminder['duration'] : 0 );

    // Will be specified in total minutes.
    $rem_rep_days = intval ( $rem_rep_minutes / 1440 );
    $rem_rep_minutes -= ( $rem_rep_days * 1440 );
    $rem_rep_hours = intval ( $rem_rep_minutes / 60 );
    $rem_rep_minutes -= ( $rem_rep_hours * 60 );

    echo ( $useTabs ? '
    <a name="tabreminder"></a>
    <div id="tabscontent_reminder">' : '
    <fieldset>
      <legend>' . translate ( 'Reminders' ) . '</legend>' ) . '
      <table border="0" cellspacing="0" cellpadding="3" summary="">
        <thead>
          <tr>
            <td class="tooltip"><label>' . translate ( 'Send Reminder' )
     . ':</label></td>
            <td colspan="3">
              <input type="hidden" name="rem_action" value="'
     . ( empty ( $reminder['action'] ) ? 'EMAIL' : $reminder['action'] ) . '" />
              <input type="hidden" name="rem_last_sent" value="'
     . ( empty ( $reminder['last_sent'] ) ? 0 : $reminder['last_sent'] ) . '" />
              <input type="hidden" name="rem_times_sent" value="'
     . ( empty ( $reminder['times_sent'] ) ? 0 : $reminder['times_sent'] )
     . '" />
                <label><input type="radio" name="reminder" '
     . 'id="reminderYes" value="1"'
     . ( $rem_status ? $checked : '' ) . ' onclick="toggle_reminders()" />'
     . translate ( 'Yes' ) . '</label>&nbsp;
                <label><input type="radio" name="reminder" '
     . 'id="reminderNo" value="0"'
     . ( $rem_status ? '' : $checked ) . ' onclick="toggle_reminders()" />'
     . translate ( 'No' ) . '</label>
            </td>
          </tr>
        </thead>
        <tbody id="reminder_when">
          <tr>
            <td class="tooltip" rowspan="6"><label>' . translate ( 'When' )
     . ':</label></td>
            <td class="boxtop boxleft" width="20%"><label><input type="radio" '
     . 'name="rem_when" id="rem_when_date" value="Y" '
     . ( $rem_use_date ? $checked : '' ) . ' onclick="toggle_rem_when()" />'
     . translate ( 'Use Date/Time' ) . '&nbsp;</label></td>
            <td class="boxtop boxright" nowrap="nowrap" colspan="2">'
     . date_selection ( 'reminder_', ( empty ( $reminder['date'] )
        ? $cal_date : $reminder['date'] ) ) . '</td>
          </tr>
          <tr>
            <td class="boxleft">&nbsp;</td>
            <td class="boxright" colspan="2" nowrap="nowrap">'
     . time_selection ( 'reminder_', ( empty ( $reminder['time'] )
        ? $cal_time : $reminder['time'] ) ) . '</td>
          </tr>
          <tr>
            <td class="boxright boxleft" height="20px" colspan="3">&nbsp;</td>
          </tr>
          <tr>
            <td class="boxleft"><label><input type="radio" name="rem_when" '
     . 'id="rem_when_offset" value="N" ' . ( $rem_use_date ? '' : $checked )
     . ' onclick="toggle_rem_when()" />' . translate ( 'Use Offset' )
     . '&nbsp;</label></td>
            <td class="boxright" nowrap="nowrap" colspan="2">
              <label><input type="text" size="2" name="rem_days" value="'
     . $rem_days . '" />' . $daysStr . '</label>&nbsp;
              <label><input type="text" size="2" name="rem_hours" '
     . 'value="' .$rem_hours . '" />' . $hoursStr . '</label>&nbsp;
              <label><input type="text" size="2" name="rem_minutes" value="'
     . $rem_minutes . '" />' . $minutStr . '</label>
            </td>
          </tr>
          <tr>
            <td class="boxleft">&nbsp;</td>
            <td><label><input type="radio" name="rem_before" '
     . 'id="rem_beforeY" value="Y"'
     . ( $rem_before ? $checked : '' ) . ' />' . translate ( 'Before' )
     . '</label>&nbsp;</td>
            <td class="boxright"><label><input type="radio" name="rem_before" '
     . 'id="rem_beforeN" value="N"' . ( $rem_before ? '' : $checked ) . ' />'
     . translate ( 'After' ) . '</label></td>
          </tr>
          <tr>
            <td class="boxbottom boxleft">&nbsp;</td>
            <td class="boxbottom"><label><input type="radio" '
     . 'name="rem_related" id="rem_relatedS" value="S"'
     . ( $rem_related ? $checked : '' ) . ' />'
     . translate ( 'Start' ) . '</label>&nbsp;</td>
            <td class="boxright boxbottom"><label><input type="radio" '
     . 'name="rem_related" id="rem_relatedE" value="E"'
     . ( $rem_related ? '' : $checked ) . ' />' . translate ( 'End/Due' )
     . '</label></td>
          </tr>
          <tr>
            <td colspan="4"></td>
          </tr>
        </tbody>
        <tbody id="reminder_repeat">
          <tr>
            <td class="tooltip" rowspan="2"><label>' . translate ( 'Repeat' )
     . ':</label></td>
            <td class="boxtop boxleft">&nbsp;&nbsp;&nbsp;<label>'
     . translate ( 'Times' ) . '</label></td>
            <td class="boxtop boxright" colspan="2"><input type="text" '
     . 'size="2" name="rem_rep_count" value="' . $rem_rep_count
     . '" onchange="toggle_rem_rep();" /></td>
          </tr>
          <tr id="rem_repeats">
            <td class="boxbottom boxleft">&nbsp;&nbsp;&nbsp;<label>'
     . translate ( 'Every' ) . '</label></td>
            <td class="boxbottom boxright" colspan="2">
              <label><input type="text" size="2" name="rem_rep_days" value="'
     . $rem_rep_days . '" />' . $daysStr . '</label>&nbsp;
              <input type="text" size="2" name="rem_rep_hours" value="'
     . $rem_rep_hours . '" /><label>' . $hoursStr . '</label>&nbsp;
              <input type="text" size="2" name="rem_rep_minutes" value="'
     . $rem_rep_minutes . '" /><label>' . $minutStr . '</label>
            </td>
          </tr>
        </tbody>
      </table>' . ( $useTabs ? '
    </div>
<!-- End tabscontent_pete -->' : '
    </fieldset>' );
  }

  if ( file_exists ( 'includes/classes/captcha/captcha.php' ) &&
      $login == '__public__' && !
      empty ( $ENABLE_CAPTCHA ) && $ENABLE_CAPTCHA == 'Y' ) {
    if ( function_exists ( 'imagecreatetruecolor' ) ) {
      include_once 'includes/classes/captcha/captcha.php';
      echo captcha::form ();
    } else
      etranslate ( 'CAPTCHA Warning' );
  }
  echo '
    </div>
<!-- End tabscontent -->';

  echo '
      <table summary="">
        <tr>
          <td>
            <script type="text/javascript">
<!-- <![CDATA[
              document.writeln ( \'<input type="button" value="'
     . $saveStr . '" onclick="validate_and_submit()" />\' )
//]]> -->
            </script>
            <noscript><input type="submit" value="' . $saveStr
     . '" /></noscript>
          </td>
        </tr>
      </table>
      <input type="hidden" name="participant_list" value="" />'
  // This bit should be moved to a webcal_fckconfig.js file.
  // Then the current FCKEditor SVN version would probably work.
       . ( $use_fckeditor ? '
      <script type="text/javascript" '
     . 'src="includes/FCKeditor-2.0/fckeditor.js"></script>
      <script type="text/javascript">
        var myFCKeditor = new FCKeditor ( \'description\' );

        myFCKeditor.BasePath = \'includes/FCKeditor-2.0/\';
        myFCKeditor.ToolbarSet = \'Medium\';
        myFCKeditor.Config[\'SkinPath\'] = \'./skins/office2003/\';
        myFCKeditor.ReplaceTextarea ();
      </script>' : '' ) . '
    </form>';

  if ( $id > 0 && ( $login == $create_by || $single_user == 'Y' || $is_admin ) )
    echo '
    <a href="del_entry.php?id=' . $id . '" onclick="return confirm( \''
     . str_replace ( 'XXX', translate ( 'entry' ),
      translate ( 'Are you sure you want to delete this XXX?' ) ) . '\' );">'
     . translate ( 'Delete entry' ) . '</a><br />';
} else
  // translate ( 'You are not authorized to edit this entry.' )
  echo str_replace ( 'XXX', translate ( 'entry' ),
    translate ( 'You are not authorized to edit this XXX.' ) );
// end if ( $can_edit )

ob_end_flush ();

echo print_trailer ();

?>

Added edit_entry_handler.php.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
<?php
/* $Id: edit_entry_handler.php,v 1.172.2.23 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require ( 'includes/classes/WebCalMailer.class' );
$mail = new WebCalMailer;
require_valide_referring_url ();

load_user_categories ();

$error = '';

$do_override = false;
$old_id = -1;

$dateStr = translate ( 'Date XXX' );
$descStr = translate ( 'Description XXX' );
$helloStr = translate ( 'Hello, XXX.' );
// translate ( 'A new appointment has been made for you by' )
$newAppStr = translate ( 'XXX has made a new appointment.' );
$subjStr = translate ( 'Subject XXX' );
$timeStr = translate ( 'Time XXX' );
// translate ( 'An appointment has been updated by' )
$updAppStr = translate ( 'XXX has updated an appointment.' );

/* Put byday values in logical sequence.
 */
function sort_byday ( $a, $b ) {
  global $byday_values;

  $len_a = strlen ( $a );
  $len_b = strlen ( $b );
  $val_a = $byday_values[substr ( $a, -2 )];
  $val_b = $byday_values[substr ( $b, -2 )];
  if ( $len_a != $len_b )
    return ( $len_a < $len_b ? -1 : 1 );
  elseif ( $len_a == 2 )
    return strcmp ( $val_a, $val_b );
  else { // They start with numeric offsets.
    $offset_a = substr ( $a, 0, $len_a - 2 );
    $offset_b = substr ( $b, 0, $len_b - 2 );
    if ( $offset_a == $offset_b )
      return strcmp ( $val_a, $val_b );
    else // Add weight to weekday value to help sort.
      return strcmp ( abs ( $offset_a ) + $val_a * 10, abs ( $offset_b ) + $val_b * 10 );
  }
}

$id = getPostValue ( 'cal_id' );
$confirm_conflicts = getPostValue ( 'confirm_conflicts' );
$override = getPostValue ( 'override' );
$override_date = getPostValue ( 'override_date' );
if ( ! empty ( $override ) && ! empty ( $override_date ) ) {
  // Override date specified.
  // User is going to create an exception to a repeating event.
  $do_override = true;
  $old_id = $id;
}

// Remember previous cal_goup_id if present.
$parent = getPostValue ( 'parent' );
$old_id = ( empty ( $parent ) ? $old_id : $parent  );
$old_status = array ();

// Pass all string values through getPostValue.
$cat_id = getValue ( 'cat_id', '-?[0-9,\-]*', true );
$description = getPostValue ( 'description' );
$participants = getPostValue ( 'participants' );
$entry_url = getPostValue ( 'entry_url' );
$eType = getPostValue ( 'eType' );
$location = getPostValue ( 'location' );
$name = getPostValue ( 'name' );
$reminder = getPostValue ( 'reminder' );

$reminder_type = getPostValue ( 'reminder_type' );
$reminder_hour = getPostValue ( 'reminder_hour' );
$reminder_minute = getPostValue ( 'reminder_minute' );
$reminder_day = getPostValue ( 'reminder_day' );
$reminder_month = getPostValue ( 'reminder_month' );
$reminder_year = getPostValue ( 'reminder_year' );

$rpt_type = getPostValue ( 'rpt_type' );
$rpt_hour = getPostValue ( 'rpt_hour' );
$rpt_minute = getPostValue ( 'rpt_minute' );
$rpt_ampm = getPostValue ( 'rpt_ampm' );
$rpt_day = getPostValue ( 'rpt_day' );
$rpt_month = getPostValue ( 'rpt_month' );
$rpt_year = getPostValue ( 'rpt_year' );

$rptmode = getPostValue ( 'rptmode' );
$rpt_end_use = getPostValue ( 'rpt_end_use' );
$rpt_count = getPostValue ( 'rpt_count' );
$rpt_freq = getPostValue ( 'rpt_freq' );
$weekdays_only = getPostValue ( 'weekdays_only' );
$wkst = getPostValue ( 'wkst' );
$bydayList = getPostValue ( 'bydayList' );
$bymonthdayList = getPostValue ( 'bymonthdayList' );
$bysetposList = getPostValue ( 'bysetposList' );
$bydayAll = getPostValue ( 'bydayAll' );
$byday = getPostValue ( 'byday' );
$bymonth = getPostValue ( 'bymonth' );
$bysetpos = getPostValue ( 'bysetpos' );
$bymonthday = getPostValue ( 'bymonthday' );
$byweekno = getPostValue ( 'byweekno' );
$byyearday = getPostValue ( 'byyearday' );
$exceptions = getPostValue ( 'exceptions' );
$timetype = getPostValue ( 'timetype' );
$priority = getPostValue ( 'priority' );
$access = getPostValue ( 'access' );
// entry_changed is calculated client-side with javascript
$entry_changed = getPostValue ( 'entry_changed' );
$rem_action = getPostValue ( 'rem_action' );
$rem_last_sent = getPostValue ( 'rem_last_sent' );
$rem_times_sent = getPostValue ( 'rem_times_sent' );
$reminder = getPostValue ( 'reminder' );
$rem_when = getPostValue ( 'rem_when' );
$rem_days = getPostValue ( 'rem_days' );
$rem_hours = getPostValue ( 'rem_hours' );
$rem_minutes = getPostValue ( 'rem_minutes' );
$rem_before = getPostValue ( 'rem_before' );
$rem_related = getPostValue ( 'rem_related' );
$rem_rep_count = getPostValue ( 'rem_rep_count' );
$rem_rep_days = getPostValue ( 'rem_rep_days' );
$rem_rep_hours = getPostValue ( 'rem_rep_hours' );
$rem_rep_minutes = getPostValue ( 'rem_rep_minutes' );
$rem_rep_minutes = getPostValue ( 'rem_rep_minutes' );

$completed_hour = getPostValue ( 'completed_hour' );
$completed_minute = getPostValue ( 'completed_minute' );
$completed_day = getPostValue ( 'completed_day' );
$completed_month = getPostValue ( 'completed_month' );
$completed_year = getPostValue ( 'completed_year' );

$due_hour = getPostValue ( 'due_hour' );
$due_minute = getPostValue ( 'due_minute' );
$due_ampm = getPostValue ( 'due_ampm' );
$due_day = getPostValue ( 'due_day' );
$due_month = getPostValue ( 'due_month' );
$due_year = getPostValue ( 'due_year' );


$description =
( strlen ( $description ) == 0 || $description == '<br />' ? $name : $description );

// For public events, we don't EVER allow HTML tags.  There is just too
// many bad things a malicious user can do.
// See this for an example of how someone could create an admin account in
// webcalendar:
//   https://www.upsploit.com/index.php/advisories/download/UPS-2010-0011
// This same technique could be used to delete all events and other bad stuff.
if ( $login == '__public__' ) {
  $name = strip_tags ( $name );
  $description = strip_tags ( $description );
  $location = strip_tags ( $location );
}

// Don't allow certain HTML tags in name, description and location.
// Malicious users can use meta refresh to redirect users to another
// site (possibly a malware site).  This could be form a public submission
// on an event calendar, and the admin gets sent to the malware site when
// viewing the event to approve/reject it.
$bannedTags = array ( 'HTML', 'HEAD', 'TITLE', 'BODY',
  'SCRIPT', 'META', 'LINK', 'OBJECT', 'APPLET' );
foreach (array($name, $description, $location) as $chkfld) {
  for ( $i = 0; $i < count ( $bannedTags ); $i++ ) {
    if ( preg_match ( "/<\s*$bannedTags[$i]/i", $chkfld ) ) {
      $error = translate('Security violation!');
      break 2;
    }
  }
}

// Pass all numeric values through getPostValue.
$entry_ampm = getPostValue ( 'entry_ampm' );
$entry_hour = getPostValue ( 'entry_hour' );
$entry_minute = getPostValue ( 'entry_minute' );

$end_ampm = getPostValue ( 'end_ampm' );
$end_hour = getPostValue ( 'end_hour' );
$end_minute = getPostValue ( 'end_minute' );

$day = getPostValue ( 'day' );
$month = getPostValue ( 'month' );
$year = getPostValue ( 'year' );

// Ensure variables are not empty.
if ( empty ( $eType ) )
  $eType = 'event';
$percent = getPostValue ( 'percent' );
if ( empty ( $percent ) )
  $percent = 0;

if ( empty ( $timetype ) )
  $timetype = 'T';

$duration_h = getValue ( 'duration_h' );
$duration_m = getValue ( 'duration_m' );

if ( empty ( $duration_h ) || $duration_h < 0 )
  $duration_h = 0;
if ( empty ( $duration_m ) || $duration_m < 0 )
  $duration_m = 0;

// Reminder values could be valid as 0
if ( empty ( $rem_days ) )
  $rem_days = 0;
if ( empty ( $rem_hours ) )
  $rem_hours = 0;
if ( empty ( $rem_minutes ) )
  $rem_minutes = 0;
if ( empty ( $rem_rep_days ) )
  $rem_rep_days = 0;
if ( empty ( $rem_rep_hours ) )
  $rem_rep_hours = 0;
if ( empty ( $rem_rep_minutes ) )
  $rem_rep_minutes = 0;
if ( empty ( $reminder_hour ) )
  $reminder_hour = 0;
if ( empty ( $reminder_minute ) )
  $reminder_minute = 0;

// Timed event.
if ( $timetype == 'T' ) {
  $entry_hour += $entry_ampm;

  if ( $eType == 'task' )
    $due_hour += $due_ampm;
}

// Use end times
if ( $TIMED_EVT_LEN == 'E' && $eType != 'task' )
  $end_hour += $end_ampm;
else
  $end_hour = $end_minute = 0;

// If "all day event" was selected, then we set the event time to be 12AM with a
// duration of 24 hours. We don't actually store the "all day event" flag per se.
// This method makes conflict checking much simpler. We just need to make sure
// that we don't screw up the day view (which normally starts with the first
// timed event). Note that if someone actually wants to create an event that
// starts at midnight and lasts exactly 24 hours, it will be treated in the
// same manner.

// All Day Event.
if ( $timetype == 'A' )
  $duration_h = 24;

// Untimed Event
if ( $timetype == 'U' )
  $duration_h = 0;

if ( strpos ( 'AU', $timetype ) !== false )
  $duration_m = $end_hour = $end_minute = $entry_hour = $entry_minute = 0;

// Combine all values to create event start date/time.
$eventstart = ( $timetype != 'T'
  ? gmmktime ( $entry_hour, $entry_minute, 0, $month, $day, $year )
  : mktime ( $entry_hour, $entry_minute, 0, $month, $day, $year ) );

if ( $eType == 'task' ) {
  // Combine all values to create event due date/time - User Time.
  $eventdue = mktime ( $due_hour, $due_minute, 0, $due_month, $due_day, $due_year );
  // Combine all values to create completed date
  if ( ! empty ( $completed_year ) && ! empty ( $completed_month ) && !
      empty ( $completed_day ) )
    $eventcomplete = sprintf ( "%04d%02d%02d", $completed_year,
      $completed_month, $completed_day );
}
// Create event stop from event duration/end values.
// Note: for any given event, either end times or durations are 0
if ( $TIMED_EVT_LEN == 'E' ) {
  //User might have entered midnight as an end time
  //if so, we need to jump to next day
  if ( $end_hour === 0 && $end_ampm == 0 )
    $day++;
  $eventstophour = $end_hour + $duration_h;
  $eventstopmin = $end_minute + $duration_m;
} else {
  $eventstophour = $entry_hour + $duration_h;
  $eventstopmin = $entry_minute + $duration_m;
}

$duration = 0;
if ( $eType != 'task' ) {
  $eventstop = ( $timetype != 'T'
    ? gmmktime ( $eventstophour, $eventstopmin, 0, $month, $day, $year )
    : mktime ( $eventstophour, $eventstopmin, 0, $month, $day, $year ) );

  // Calculate event duration.
  if ( $timetype == 'A' )
    $duration = 1440;
  elseif ( $timetype == 'T' ) {
    $duration = ( $eventstop - $eventstart ) / 60;
    if ( $duration < 0 )
      $duration = 0;
  }
}

// Make sure this user is really allowed to edit this event.
// Otherwise, someone could hand type in the URL to edit someone else's event.
// Can edit if:
//   - new event
//   - user is admin
//   - user created event
//   - user is participant
$can_doall = $can_edit = false;
// Value may be needed later for recreating event.
$user = getPostValue ( 'user' );
$old_create_by = ( empty ( $user ) ? '' : $user );
if ( empty ( $id ) )
  // New event...
  $can_edit = true;
else {
  // Event owner or assistant?
  $res = dbi_execute ( 'SELECT cal_create_by FROM webcal_entry WHERE cal_id = ?',
    array ( $id ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    // Value may be needed later for recreating event.
    $old_create_by = $row[0];
    if ( ( $row[0] == $login ) || ( ( $user == $row[0] ) &&
          ( $is_assistant || $is_nonuser_admin ) ) )
      $can_edit = true;
    dbi_free_result ( $res );
  } else
    $error = $dberror . dbi_error ();
}

if ( $is_admin )
  $can_edit = true;
else
if ( access_is_enabled () && ! empty ( $old_create_by ) )
  $can_edit = access_user_calendar ( 'edit', $old_create_by, $login );

if ( empty ( $error ) && ! $can_edit ) {
  // Is user a participant of that event?
  $res = dbi_execute ( 'SELECT cal_id FROM webcal_entry_user WHERE cal_id = ?
    AND cal_login = ? AND cal_status IN ( \'W\',\'A\' )', array ( $id, $login ) );
  if ( $res ) {
    $row = dbi_fetch_row ( $res );
    if ( ! empty ( $row[0] ) )
      $can_edit = true; // Is participant.
    dbi_free_result ( $res );
  } else
    $error = $dberror . dbi_error ();
}

if ( ! $can_edit && empty ( $error ) )
  $error = print_not_auth (6);

// CAPTCHA
if ( file_exists ( 'includes/classes/captcha/captcha.php' ) && $login == '__public__' && !
    empty ( $ENABLE_CAPTCHA ) && $ENABLE_CAPTCHA == 'Y' ) {
  if ( function_exists ( 'imagecreatetruecolor' ) ) {
    include_once 'includes/classes/captcha/captcha.php';
    $res = captcha::check ();
    if ( ! $res )
      $error = translate ( 'You must enter the anti-spam text on the previous page.' );
  } else {
    // Should have seen warning on edit_entry.php, so no warning here...
  }
}
// If display of participants is disabled, set the participant list
// to the event creator. This also works for single-user mode.
// Basically, if no participants were selected (because there
// was no selection list available in the form or because the user
// refused to select any participant from the list), then we will
// assume the only participant is the current user.
if ( empty ( $participants[0] ) ) {
  $participants[0] = $login;
  // There might be a better way to do this,
  // but if Admin sets this value, WebCalendar should respect it.
  if ( ! empty ( $PUBLIC_ACCESS_DEFAULT_SELECTED ) && $PUBLIC_ACCESS_DEFAULT_SELECTED == 'Y' )
    $participants[1] = '__public__';
}

if ( empty ( $DISABLE_REPEATING_FIELD ) || $DISABLE_REPEATING_FIELD == 'N' ) {
  // Process only if Expert Mode or Weekly.
  if ( $rpt_type == 'weekly' || ! empty ( $rptmode ) ) {
    $bydayAr = explode ( ',', $bydayList );
    if ( ! empty ( $bydayAr ) ) {
      foreach ( $bydayAr as $bydayElement ) {
        if ( strlen ( $bydayElement ) > 2 )
          $bydayAll[] = $bydayElement;
      }
    }

    if ( ! empty ( $bydayAll ) ) {
      $bydayAll = array_unique ( $bydayAll );
      // Call special sort algorithm.
      usort ( $bydayAll, 'sort_byday' );
      $byday = implode ( ',', $bydayAll );
      // Strip off leading comma if present.
      if ( substr ( $byday, 0, 1 ) == ',' )
        $byday = substr ( $byday, 1 );
    }
  }
  // This allows users to select on weekdays if daily.
  if ( $rpt_type == 'daily' && ! empty ( $weekdays_only ) )
    $byday = 'MO,TU,WE,TH,FR';

  // Process only if expert mode and MonthbyDate or Yearly.
  if ( ( $rpt_type == 'monthlyByDate' || $rpt_type == 'yearly' ) && !
      empty ( $rptmode ) ) {
    $bymonthdayAr = explode ( ',', $bymonthdayList );
    if ( ! empty ( $bymonthdayAr ) ) {
      sort ( $bymonthdayAr );
      $bymonthdayAr = array_unique ( $bymonthdayAr );
      $bymonthday = implode ( ',', $bymonthdayAr );
    }
    // Strip off leading comma if present.
    if ( substr ( $bymonthday, 0, 1 ) == ',' )
      $bymonthday = substr ( $bymonthday, 1 );
  }

  if ( $rpt_type == 'monthlyBySetPos' ) {
    $bysetposAr = explode ( ',', $bysetposList );
    if ( ! empty ( $bysetposAr ) ) {
      sort ( $bysetposAr );
      $bysetposAr = array_unique ( $bysetposAr );
      $bysetpos = implode ( ',', $bysetposAr );
    }
    // Strip off leading comma if present.
    if ( substr ( $bysetpos, 0, 1 ) == ',' )
      $bysetpos = substr ( $bysetpos, 1 );
  }
  // If expert mode not selected,
  // we need to set the basic value for monthlyByDay events.
  if ( $rpt_type == 'monthlyByDay' && empty ( $rptmode ) && empty ( $byday ) )
    $byday = ceil ( $day / 7 ) . $byday_names[ date ( 'w', $eventstart ) ];

  $bymonth = ( empty ( $bymonth ) ? '' : implode ( ',', $bymonth ) );

  if ( ! empty ( $rpt_year ) ) {
    $rpt_hour += $rpt_ampm;
    $rpt_until = mktime ( $rpt_hour, $rpt_minute, 0, $rpt_month, $rpt_day, $rpt_year );
  }

  $exception_list = $inclusion_list = array ();
  if ( empty ( $exceptions ) )
    $exceptions = array ();
  else {
    foreach ( $exceptions as $exception ) {
      if ( substr ( $exception, 0, 1 ) == '+' )
        $inclusion_list[] = substr ( $exception, 1, 8 );
      else
        $exception_list[] = substr ( $exception, 1, 8 );
    }
  }
} // end test for $DISABLE_REPEATING_FIELD
// Make sure we initialize these variables.
if ( empty ( $byday ) )
  $byday = '';
if ( empty ( $bymonth ) )
  $bymonth = '';
if ( empty ( $bymonthday ) )
  $bymonthday = '';
if ( empty ( $bysetpos ) )
  $bysetpos = '';
if ( empty ( $byweekno ) )
  $byweekno = '';
if ( empty ( $byyearday ) )
  $byyearday = '';
if ( empty ( $count ) )
  $count = '';
if ( empty ( $rpt_freq ) )
  $rpt_freq = 1;
if ( empty ( $rpt_type ) )
  $rpt_type = '';
if ( empty ( $wkst ) )
  $wkst = 'MO';

// First check for any schedule conflicts.
if ( empty ( $ALLOW_CONFLICT_OVERRIDE ) || $ALLOW_CONFLICT_OVERRIDE != 'Y' )
  $confirm_conflicts = ''; // Security precaution.

if ( $ALLOW_CONFLICTS != 'Y' && empty ( $confirm_conflicts ) &&
    strlen ( $entry_hour ) > 0 && $timetype != 'U' && $eType != 'task' ) {
  $conf_until = ( empty ( $rpt_until ) ? '' : $rpt_until );
  $conf_count = ( empty ( $count ) ? 999 : $count );
  $dates = get_all_dates ( $eventstart, $rpt_type, $rpt_freq, 
	  array ( $bymonth, $byweekno, $byyearday, $bymonthday, $byday, $bysetpos ),
	  $conf_count, $conf_until, $wkst, $exception_list, $inclusion_list );

  // Make sure at least start date is in array.
  if ( empty ( $dates ) )
    $dates[0] = $eventstart;

  // Make sure $thismonth and $thisyear are set for use in query_events ().
  $thismonth = $month;
  $thisyear = $year;
  $conflicts = check_for_conflicts ( $dates, $duration, $eventstart,
    $participants, $login, empty ( $id ) ? 0 : $id );
} //end check for any schedule conflicts

if ( empty ( $error ) && ! empty ( $conflicts ) )
  $error = translate ( 'The following conflicts with the suggested time' )
   . ': <ul>$conflicts</ul>';

$msg = '';
if ( empty ( $error ) ) {
  $newevent = true;
  // Now add the entries.
  if ( empty ( $id ) || $do_override ) {
    $res = dbi_execute ( 'SELECT MAX(cal_id) FROM webcal_entry' );
    if ( $res ) {
      $row = dbi_fetch_row ( $res );
      $id = $row[0] + 1;
      dbi_free_result ( $res );
    } else
      $id = 1;
  } else {
    $newevent = false;
    // Save old values of participants.
    $res = dbi_execute ( 'SELECT cal_login, cal_status, cal_percent
      FROM webcal_entry_user WHERE cal_id = ? ', array ( $id ) );
    if ( $res ) {
      for ( $i = 0; $tmprow = dbi_fetch_row ( $res ); $i++ ) {
        $old_status[$tmprow[0]] = $tmprow[1];
        $old_percent[$tmprow[0]] = $tmprow[2];
      }
      dbi_free_result ( $res );
    } else
      $error = $dberror . dbi_error ();

    if ( empty ( $error ) ) {
      dbi_execute ( 'DELETE FROM webcal_entry WHERE cal_id = ?', array ( $id ) );
      dbi_execute ( 'DELETE FROM webcal_entry_ext_user WHERE cal_id = ?', array ( $id ) );
      dbi_execute ( 'DELETE FROM webcal_entry_repeats WHERE cal_id = ?', array ( $id ) );
      dbi_execute ( 'DELETE FROM webcal_entry_user WHERE cal_id = ?', array ( $id ) );
      dbi_execute ( 'DELETE FROM webcal_site_extras WHERE cal_id = ?', array ( $id ) );
    }
    $newevent = false;
  }

  if ( $do_override ) {
    if ( ! dbi_execute ( 'INSERT INTO webcal_entry_repeats_not
      ( cal_id, cal_date, cal_exdate ) VALUES ( ?, ?, ? )',
        array ( $old_id, $override_date, 1 ) ) )
      $error = $dberror . dbi_error ();
  }

  $query_params = array ();
  $query_params[] = $id;
  if ( $old_id > 0 )
    $query_params[] = $old_id;

  $query_params[] = ( empty ( $old_create_by ) ? $login : $old_create_by );
  $query_params[] = gmdate ( 'Ymd', $eventstart );
  $query_params[] = ( ( strlen ( $entry_hour ) > 0 && $timetype != 'U' )
    ? gmdate ( 'His', $eventstart ) : '-1' );

  if ( ! empty ( $eventcomplete ) )
    $query_params[] = $eventcomplete;

  // Just set $eventdue to something.
  $eventdue = ( empty ( $eventdue ) ? $eventstart : $eventdue );

  $query_params[] = gmdate ( 'Ymd', $eventdue );
  $query_params[] = gmdate ( 'His', $eventdue );
  $query_params[] = gmdate ( 'Ymd' );
  $query_params[] = gmdate ( 'Gis' );
  $query_params[] = sprintf ( "%d", $duration );
  $query_params[] = ( empty ( $priority ) ? '5' : sprintf ( "%d", $priority ) );
  $query_params[] = ( empty ( $access ) ? 'P' : $access );

  $tmpRpt = ( ! empty ( $rpt_type ) && $rpt_type != 'none' );

  if ( $eType == 'event' )
    $query_params[] = ( $tmpRpt ? 'M' : 'E' );
  elseif ( $eType == 'journal' )
    $query_params[] = ( $tmpRpt ? 'O' : 'J' );
  elseif ( $eType == 'task' )
    $query_params[] = ( $tmpRpt ? 'N' : 'T' );

  $query_params[] = ( strlen ( $name ) == 0 ? 'Unnamed Event' : $name );
  $query_params[] = $description;

  if ( ! empty ( $location ) )
    $query_params[] = $location;

  if ( ! empty ( $entry_url ) )
    $query_params[] = $entry_url;

  if ( empty ( $error ) && ! dbi_execute ( 'INSERT INTO webcal_entry ( cal_id, '
         . ( $old_id > 0 ? ' cal_group_id, ' : '' )
         . 'cal_create_by, cal_date, cal_time, '
         . ( empty ( $eventcomplete ) ? '' : 'cal_completed, ' )
         . 'cal_due_date, cal_due_time, cal_mod_date, cal_mod_time, cal_duration, '
         . 'cal_priority, cal_access, cal_type, cal_name, cal_description '
         . ( empty ( $location ) ? '' : ',cal_location ' )
         . ( empty ( $entry_url ) ? '' : ',cal_url ' ) . ' ) VALUES ( ?, '
         . ( $old_id > 0 ? '?, ' : '' ) . '?, ?, ?, '
         . ( empty ( $eventcomplete ) ? '' : '?, ' )
         . '?, ?, ?, ?, ?, ?, ?, ?, ?, ? '
         . ( empty ( $location ) ? '' : ',? ' )
         . ( empty ( $entry_url ) ? '' : ',? ' ) . ')', $query_params ) ) {
    $error = $dberror . dbi_error ();
  }
  // Log add/update.
  if ( $eType == 'task' ) {
    $log_c = LOG_CREATE_T;
    $log_u = LOG_UPDATE_T;
  } elseif ( $eType == 'journal' ) {
    $log_c = LOG_CREATE_J;
    $log_u = LOG_UPDATE_J;
  } else {
    $log_c = LOG_CREATE;
    $log_u = LOG_UPDATE;
  }
  activity_log ( $id, $login, ( $is_assistant || $is_nonuser_admin ? $user : $login ),
    $newevent ? $log_c : $log_u, '' );

  if ( $single_user == 'Y' )
    $participants[0] = $single_user_login;

  // Add categories.
  $cat_owner = ( ( ! empty ( $user ) && strlen ( $user ) ) &&
    ( $is_assistant || $is_admin ) ) ? $user : $login;
  dbi_execute ( 'DELETE FROM webcal_entry_categories WHERE cal_id = ?
    AND ( cat_owner = ? OR cat_owner IS NULL )', array ( $id, $cat_owner ) );
  if ( ! empty ( $cat_id ) ) {
    $categories = explode ( ',', $cat_id );
    $categorycnt = count ( $categories );
    for ( $i = 0; $i < $categorycnt; $i++ ) {
      $names = $values = array ();

      $names[] = 'cal_id';
      $values[] = $id;

      $names[] = 'cat_id';
      $values[] = abs ( $categories[$i] );

      // We set cat_id negative in form if global.
      if ( $categories[$i] > 0 ) {
        $names[] = 'cat_owner';
        $values[] = $cat_owner;

        $names[] = 'cat_order';
        $values[] = ( $i + 1 );
      } else {
        $names[] = 'cat_order';
        $values[] = 99; // Forces global categories to appear at the end of lists.
      }
      // Build the variable placeholders - comma-separated question marks.
      $placeholders = '';
      $valuecnt = count ( $values );
      for ( $v_i = 0; $v_i < $valuecnt; $v_i++ ) {
        $placeholders .= '?,';
      }
      $placeholders = preg_replace ( '/,$/', '', $placeholders ); // Remove trailing ','.
      if ( ! dbi_execute ( 'INSERT INTO webcal_entry_categories ( '
           . implode ( ', ', $names )
           . ' ) VALUES ( ' . $placeholders . ' )', $values ) ) {
        $error = $dberror . dbi_error ();
        break;
      }
    }
  }
  // Add site extras.
  $site_extracnt = count ( $site_extras );
  $extra_email_data = '';
  for ( $i = 0; $i < $site_extracnt && empty ( $error ); $i++ ) {
    if ( $site_extras[$i] == 'FIELDSET' )
      continue;
    $extra_name = $site_extras[$i][0];
    $extra_type = $site_extras[$i][2];
    $extra_arg1 = $site_extras[$i][3];
    $extra_arg2 = $site_extras[$i][4];
    if ( ! empty ( $site_extras[$i][5] ) )
      $extra_email = $site_extras[$i][5] & EXTRA_DISPLAY_EMAIL;

    //$value = $$extra_name;
    $value = getPostValue ( $extra_name );
    // echo "Looking for $extra_name... value = " . $value . " ... type = " .
    // $extra_type . "<br />\n";
    $sql = '';
    $query_params = array ();

    if ( strlen ( $extra_name ) || $extra_type == EXTRA_DATE ) {
      if ( $extra_type == EXTRA_URL || $extra_type == EXTRA_EMAIL ||
        $extra_type == EXTRA_TEXT || $extra_type == EXTRA_USER ||
        $extra_type == EXTRA_MULTILINETEXT || $extra_type == EXTRA_SELECTLIST ||
        $extra_type == EXTRA_RADIO || $extra_type == EXTRA_CHECKBOX ) {
        // We were passed an array instead of a string.
        if ( $extra_type == EXTRA_SELECTLIST && $extra_arg2 > 0 )
          $value = implode ( ',', $value );

        $sql = 'INSERT INTO webcal_site_extras ( cal_id, cal_name, cal_type,
          cal_data ) VALUES ( ?, ?, ?, ? )';
        $query_params = array ( $id, $extra_name, $extra_type, $value );
        if ( ! empty ( $extra_email ) ) {
          $value = ( $extra_type == EXTRA_RADIO ? $extra_arg1[$value] : $value );
          $extra_email_data .= $extra_name . ': ' . $value . "\n";
        }
      } else
      if ( $extra_type == EXTRA_DATE ) {
        $dname = getPostValue ( $extra_name . 'day' );
        $mname = getPostValue ( $extra_name . 'month' );
        $yname = getPostValue ( $extra_name . 'year' );
        $edate = sprintf ( "%04d%02d%02d", $yname, $mname, $dname );
        $sql = 'INSERT INTO webcal_site_extras ( cal_id, cal_name, cal_type,
          cal_date ) VALUES ( ?, ?, ?, ? )';
        $query_params = array ( $id, $extra_name, $extra_type, $edate );
        if ( ! empty ( $extra_email ) )
          $extra_email_data .= $extra_name . ': ' . $edate . "\n";
      }
    }
    if ( strlen ( $sql ) && empty ( $error ) ) {
      if ( ! dbi_execute ( $sql, $query_params ) )
        $error = $dberror . dbi_error ();
    }
  } //end for site_extras loop
  // Process reminder.
  if ( ! dbi_execute ( 'DELETE FROM webcal_reminders WHERE cal_id = ?',
      array ( $id ) ) )
    $error = $dberror . dbi_error ();

  if ( $DISABLE_REMINDER_FIELD != 'Y' && $reminder == true ) {
    if ( empty ( $rem_before ) )
      $rem_before = 'Y';

    if ( empty ( $rem_last_sent ) )
      $rem_last_sent = '0';

    if ( empty ( $rem_related ) )
      $rem_related = 'S';

    $reminder_date = $reminder_duration = $reminder_offset = $reminder_repeats = 0;
    if ( $rem_when == 'Y' ) { // Use date.
      $reminder_hour += $reminder_ampm;
      $reminder_date = mktime ( $reminder_hour, $reminder_minute, 0,
        $reminder_month, $reminder_day, $reminder_year );
    } else // Use offset.
      $reminder_offset = ( $rem_days * 1440 ) + ( $rem_hours * 60 ) + $rem_minutes;

    if ( $rem_rep_count > 0 ) {
      $reminder_repeats = $rem_rep_count;
      $reminder_duration = ( $rem_rep_days * 1440 ) +
      ( $rem_rep_hours * 60 ) + $rem_rep_minutes;
    }
    if ( ! dbi_execute ( 'INSERT INTO webcal_reminders ( cal_id, cal_date,
      cal_offset, cal_related, cal_before, cal_repeats, cal_duration, cal_action,
      cal_last_sent, cal_times_sent ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )',
        array ( $id, $reminder_date, $reminder_offset, $rem_related, $rem_before,
          $reminder_repeats, $reminder_duration, $rem_action, $rem_last_sent,
          $rem_times_sent ) ) )
      $error = $dberror . dbi_error ();
  }
  // Clearly, we want to delete the old repeats, before inserting new...
  if ( empty ( $error ) ) {
    if ( ! dbi_execute ( 'DELETE FROM webcal_entry_repeats WHERE cal_id = ?',
        array ( $id ) ) )
      $error = $dberror . dbi_error ();

    if ( ! dbi_execute ( 'DELETE FROM webcal_entry_repeats_not WHERE cal_id = ?',
        array ( $id ) ) )
      $error = $dberror . dbi_error ();

    // Add repeating info.
    if ( ! empty ( $rpt_type ) && strlen ( $rpt_type ) && $rpt_type != 'none' ) {
      $freq = ( $rpt_freq ? $rpt_freq : 1 );
      $names = $values = array ();

      $names[] = 'cal_id';
      $values[] = $id;

      $names[] = 'cal_type';
      $values[] = $rpt_type;

      $names[] = 'cal_frequency';
      $values[] = $freq;

      if ( ! empty ( $bymonth ) ) {
        $names[] = 'cal_bymonth';
        $values[] = $bymonth;
      }
      if ( ! empty ( $bymonthday ) ) {
        $names[] = 'cal_bymonthday';
        $values[] = $bymonthday;
      }
      if ( ! empty ( $byday ) ) {
        $names[] = 'cal_byday';
        $values[] = $byday;
      }
      if ( ! empty ( $bysetpos ) ) {
        $names[] = 'cal_bysetpos';
        $values[] = $bysetpos;
      }
      if ( ! empty ( $byweekno ) ) {
        $names[] = 'cal_byweekno';
        $values[] = $byweekno;
      }
      if ( ! empty ( $byyearday ) ) {
        $names[] = 'cal_byyearday';
        $values[] = $byyearday;
      }
      if ( ! empty ( $wkst ) ) {
        $names[] = 'cal_wkst';
        $values[] = $wkst;
      }
      if ( ! empty ( $rpt_count ) && is_numeric ( $rpt_count ) ) {
        $names[] = 'cal_count';
        $values[] = $rpt_count;
      }
      if ( ! empty ( $rpt_until ) ) {
        $names[] = 'cal_end';
        $values[] = gmdate ( 'Ymd', $rpt_until );

        $names[] = 'cal_endtime';
        $values[] = gmdate ( 'His', $rpt_until );
      }
      $placeholders = '';
      $valuecnt = count ( $values );
      for ( $v_i = 0; $v_i < $valuecnt; $v_i++ ) {
        $placeholders .= '?,';
      }
      $placeholders = preg_replace ( '/,$/', '', $placeholders ); // Remove trailing ','.
      $sql = 'INSERT INTO webcal_entry_repeats ( '
       . implode ( ', ', $names ) . ' ) VALUES ( ' . $placeholders . ' )';
      dbi_execute ( $sql, $values );
      $msg .= '<span class="bold">SQL:</span> ' . $sql . '<br /><br />';
    } //end add repeating info
    // We manually created exceptions. This can be done without repeats.
    if ( ! empty ( $exceptions ) ) {
      $exceptcnt = count ( $exceptions );
      for ( $i = 0; $i < $exceptcnt; $i++ ) {
        if ( ! dbi_execute ( 'INSERT INTO webcal_entry_repeats_not
          ( cal_id, cal_date, cal_exdate ) VALUES ( ?, ?, ? )',
            array ( $id, substr ( $exceptions[$i], 1, 8 ),
                ( ( substr ( $exceptions[$i], 0, 1 ) == '+' ) ? 0 : 1 ) ) ) )
          $error = $dberror . dbi_error ();
      }
    } //end exceptions
  }
  // EMAIL PROCESSING
  $partcnt = count ( $participants );
  $from = $login_email;
  if ( empty ( $from ) && ! empty ( $EMAIL_FALLBACK_FROM ) )
    $from = $EMAIL_FALLBACK_FROM;
  // Check if participants have been removed and send out emails.
  if ( ! $newevent && count ( $old_status ) > 0 ) {
    while ( list ( $old_participant, $dummy ) = each ( $old_status ) ) {
      $found_flag = false;
      for ( $i = 0; $i < $partcnt; $i++ ) {
        if ( $participants[$i] == $old_participant ) {
          $found_flag = true;
          break;
        }
      }
      // Check UAC.
      $can_email = 'Y';
      if ( access_is_enabled () )
        $can_email = access_user_calendar ( 'email', $old_participant, $login );

      $is_nonuser_admin = user_is_nonuser_admin ( $login, $old_participant );
      // Don't send mail if we are editing a non-user calendar and we are the admin.
      if ( !$found_flag && !$is_nonuser_admin && $can_email == 'Y' ) {
        // Only send mail if their email address is filled in.
        $do_send = get_pref_setting ( $old_participant, 'EMAIL_EVENT_DELETED' );
        $htmlmail = get_pref_setting ( $old_participant, 'EMAIL_HTML' );
        $t_format = get_pref_setting ( $old_participant, 'TIME_FORMAT' );
        $user_TIMEZONE = get_pref_setting ( $old_participant, 'TIMEZONE' );
        set_env ( 'TZ', $user_TIMEZONE );
        $user_language = get_pref_setting ( $old_participant, 'LANGUAGE' );
        user_load_variables ( $old_participant, 'temp' );

        if ( $old_participant != $login && !
          empty ( $tempemail ) && $do_send == 'Y' && $SEND_EMAIL != 'N' ) {
          reset_language ( empty ( $user_language ) || ( $user_language == 'none' )
            ? $LANGUAGE : $user_language );

          $fmtdate = ( $timetype == 'T'
            ? date ( 'Ymd', $eventstart ) : gmdate ( 'Ymd', $eventstart ) );
          $msg = str_replace ( 'XXX', $tempfullname, $helloStr ) . "\n\n"
          // translate ( 'An appointment has been canceled for you by' )
          . str_replace ( 'XXX', $login_fullname,
            translate ( 'XXX has canceled an appointment.' ) ) . "\n"
           . str_replace ( 'XXX', $name, $subjStr ) . "\n\n"
           . str_replace ( 'XXX', $description, $descStr ) . "\n"
           . str_replace ( 'XXX', date_to_str ( $fmtdate ), $dateStr )
           . "\n"
          // Apply user's GMT offset and display their TZID.
          . ( $timetype != 'T'
            ? '' : str_replace ( 'XXX',
              display_time ( '', 2, $eventstart, $t_format ), $timeStr . "\n\n\n" ) );
          // Add URL to event, if we can figure it out.
          if ( ! empty ( $SERVER_URL ) ) {
            // DON'T change & to &amp; here. Email will handle it.
            $url = $SERVER_URL . 'view_entry.php?id=' . $id . '&em=1';
            if ( $htmlmail == 'Y' )
              $url = activate_urls ( $url );

            $msg .= $url . "\n\n";
          }
          $wantsAttach = get_pref_setting ( $old_participant,
            'EMAIL_ATTACH_ICS', 'N' );
          $attachId = ( $wantsAttach == 'Y' ? $id : '' );
          $mail->WC_Send ( $login_fullname, $tempemail,
            $tempfullname, $name, $msg, $htmlmail, $from, $attachId );
          activity_log ( $id, $login, $old_participant, LOG_NOTIFICATION,
            translate ( 'User removed from participants list.' ) );
        }
      }
    }
  }
  $send_own = get_pref_setting ( $login, 'EMAIL_EVENT_CREATE' );
  // Now add participants and send out notifications.
  for ( $i = 0; $i < $partcnt; $i++ ) {
    // Is the person adding the nonuser calendar admin?
    $is_nonuser_admin = user_is_nonuser_admin ( $login, $participants[$i] );
    // If public access, require approval unless
    // $PUBLIC_ACCESS_ADD_NEEDS_APPROVAL is set to 'N'
    if ( $login == '__public__' ) {
      $status = ( ! empty ( $PUBLIC_ACCESS_ADD_NEEDS_APPROVAL ) &&
        $PUBLIC_ACCESS_ADD_NEEDS_APPROVAL == 'N'
        ? 'A' // No approval needed.
        : 'W' // Approval required.
        );
      // Percent will always be 0 for Public
      $new_percent = 0;
    } else
    if ( ! $newevent ) {
      // Keep the old status if no email will be sent.
      $send_user_mail = ( empty ( $old_status[$participants[$i]] ) || $entry_changed );
      $tmp_status = ( ! empty ( $old_status[$participants[$i]] ) && ! $send_user_mail
        ? $old_status[$participants[$i]] : 'W' );
      $status = ( $participants[$i] != $login &&
        boss_must_approve_event ( $login, $participants[$i] ) &&
        $REQUIRE_APPROVALS == 'Y' && ! $is_nonuser_admin ? $tmp_status : 'A' );

      // Set percentage to old_percent if not owner.
      $tmp_percent = ( empty ( $old_percent[$participants[$i]] )
        ? 0 : $old_percent[$participants[$i]] );
      // TODO:  This logic needs work.
      $new_percent = ( $participants[$i] != $login
        ? $tmp_percent : $percent );
      // If user is admin and this event was previously approved for public,
      // keep it as approved even though date/time may have changed.
      // This goes against stricter security, but it confuses users to have
      // to re-approve events they already approved.
      if ( $participants[$i] == '__public__' && $is_admin &&
        ( empty ( $old_status['__public__'] ) || $old_status['__public__'] == 'A' ) )
        $status = 'A';
    } else { // New Event.
      $send_user_mail = true;
      $status = ( $participants[$i] != $login &&
        boss_must_approve_event ( $login, $participants[$i] ) &&
        $REQUIRE_APPROVALS == 'Y' && ! $is_nonuser_admin ? 'W' : 'A' );
      $new_percent = ( $participants[$i] != $login ? 0 : $percent );
      // If admin, no need to approve Public Access Events
      if ( $participants[$i] == '__public__' && $is_admin )
        $status = 'A';
    } //end new/old event

    // Some users report that they get an error on duplicate keys
    // on the following add... As a safety measure, delete any
    // existing entry with the id. Ignore the result.
    dbi_execute ( 'DELETE FROM webcal_entry_user WHERE cal_id = ? AND cal_login = ?',
      array ( $id, $participants[$i] ) );
    if ( ! dbi_execute ( 'INSERT INTO webcal_entry_user ( cal_id, cal_login,
      cal_status, cal_percent ) VALUES ( ?, ?, ?, ? )',
        array ( $id, $participants[$i], $status, $new_percent ) ) ) {
      $error = $dberror . dbi_error ();
      break;
    } else {
      // Check UAC.
      $can_email = 'Y';
      if ( access_is_enabled () )
        $can_email = access_user_calendar ( 'email', $participants[$i], $login );

      // Don't send mail if we are editing a non-user calendar and we are the admin.
      if ( !$is_nonuser_admin && $can_email == 'Y' ) {
        // Only send mail if their email address is filled in.
        $do_send = get_pref_setting ( $participants[$i], $newevent
          ? 'EMAIL_EVENT_ADDED' : 'EMAIL_EVENT_UPDATED' );
        $htmlmail = get_pref_setting ( $participants[$i], 'EMAIL_HTML' );
        $t_format = get_pref_setting ( $participants[$i], 'TIME_FORMAT' );
        $user_TIMEZONE = get_pref_setting ( $participants[$i], 'TIMEZONE' );
        set_env ( 'TZ', $user_TIMEZONE );
        $user_language = get_pref_setting ( $participants[$i], 'LANGUAGE' );
        user_load_variables ( $participants[$i], 'temp' );
        if ( boss_must_be_notified ( $login, $participants[$i] ) && !
            empty ( $tempemail ) && $do_send == 'Y' && $send_user_mail && $SEND_EMAIL != 'N' ) {
          // We send to creator if they want it.
          if ( $send_own != 'Y' && ( $participants[$i] == $login ) )
            continue;

          reset_language ( empty ( $user_language ) || ( $user_language == 'none' )
            ? $LANGUAGE : $user_language );
          $fmtdate = ( $timetype == 'T'
            ? date ( 'Ymd', $eventstart ): gmdate ( 'Ymd', $eventstart ) );
          $msg = str_replace ( 'XXX', $tempfullname, $helloStr ) . "\n\n"
           . str_replace ( 'XXX', $login_fullname,
            ( $newevent || ( empty ( $old_status[$participants[$i]] ) )
              ? $newAppStr : $updAppStr ) ) . "\n"
           . str_replace ( 'XXX', $name, $subjStr ) . "\n\n"
           . str_replace ( 'XXX', $description, $descStr ) . "\n"
           . str_replace ( 'XXX', date_to_str ( $fmtdate ), $dateStr )
           . "\n"
          // Apply user's GMT offset and display their TZID
          . ( $timetype != 'T' ? ''
            : str_replace ( 'XXX', display_time ( '', 2, $eventstart, $t_format ),
              $timeStr ) . "\n" )
          // Add Site Extra Date if permitted.
          . $extra_email_data
          // translate ( 'Please look on' )
          // translate ( 'to accept or reject this appointment' )
          // translate ( 'to view this appointment' )
          . str_replace ( 'XXX', generate_application_name (),
            ( $REQUIRE_APPROVALS == 'Y'
              ? translate ( 'Please look on XXX to accept or reject this appointment.' )
              : translate ( 'Please look on XXX to view this appointment.' ) ) );
          // Add URL to event, if we can figure it out.
          if ( ! empty ( $SERVER_URL ) ) {
            // DON'T change & to &amp; here. Email will handle it.
            $url = $SERVER_URL . 'view_entry.php?id=' . $id . '&em=1';
            if ( $htmlmail == 'Y' )
              $url = activate_urls ( $url );

            $msg .= "\n\n" . $url;
          }
          $wantsAttach = get_pref_setting ( $participants[$i],
            'EMAIL_ATTACH_ICS', 'N' );
          $attachId = ( $wantsAttach == 'Y' ? $id : '' );
          // Use WebCalMailer class.
          $mail->WC_Send ( $login_fullname, $tempemail,
            $tempfullname, $name, $msg, $htmlmail, $from, $attachId );
          activity_log ( $id, $login, $participants[$i], LOG_NOTIFICATION, '' );
        }
      }
    }
  } //end for loop participants

  // Add external participants.
  $ext_emails = $ext_names = $matches = array ();
  $ext_count = 0;
  $externalparticipants = getPostValue ( 'externalparticipants' );
  if ( $single_user == 'N' && !
    empty ( $ALLOW_EXTERNAL_USERS ) && $ALLOW_EXTERNAL_USERS == 'Y' && !
      empty ( $externalparticipants ) ) {
    $lines = explode ( "\n", $externalparticipants );
    if ( ! is_array ( $lines ) )
      $lines = array ( $externalparticipants );

    if ( is_array ( $lines ) ) {
      $linecnt = count ( $lines );
      for ( $i = 0; $i < $linecnt; $i++ ) {
        $ext_words = explode ( ' ', $lines[$i] );
        if ( ! is_array ( $ext_words ) )
          $ext_words = array ( $lines[$i] );

        if ( is_array ( $ext_words ) ) {
          $ext_wordscnt = count ( $ext_words );
          $ext_emails[$ext_count] = $ext_names[$ext_count] = '';
          for ( $j = 0; $j < $ext_wordscnt; $j++ ) {
            // Use regexp matching to pull email address out.
            $ext_words[$j] = chop ( $ext_words[$j] ); // Remove \r if there is one.
            if ( preg_match ( '/<?\\S+@\\S+\\.\\S+>?/', $ext_words[$j], $matches ) ) {
              $ext_emails[$ext_count] = $matches[0];
              $ext_emails[$ext_count] = preg_replace ( '/[<>]/', '',
                $ext_emails[$ext_count] );
            } else {
              if ( strlen ( $ext_names[$ext_count] ) )
                $ext_names[$ext_count] .= ' ';

              $ext_names[$ext_count] .= $ext_words[$j];
            }
          }
          // Test for duplicate Names.
          if ( $i > 0 ) {
            for ( $k = $i - 1; $k > 0; $k-- ) {
              if ( $ext_names[$i] == $ext_names[$k] )
                $ext_names[$i] .= "[$k]";
            }
          }
          if ( strlen ( $ext_emails[$ext_count] ) &&
              empty ( $ext_names[$ext_count] ) )
            $ext_names[$ext_count] = $ext_emails[$ext_count];

          $ext_count++;
        }
      }
    }
  }
  // Send notification if enabled.
  if ( is_array ( $ext_names ) && is_array ( $ext_emails ) ) {
    $ext_namescnt = count ( $ext_names );
    for ( $i = 0; $i < $ext_namescnt; $i++ ) {
      if ( strlen ( $ext_names[$i] ) ) {
        if ( ! dbi_execute ( 'INSERT INTO webcal_entry_ext_user
          ( cal_id, cal_fullname, cal_email ) VALUES ( ?, ?, ? )',
            array ( $id, $ext_names[$i],
              ( strlen ( $ext_emails[$i] ) ? $ext_emails[$i] : null ) ) ) )
          $error = $dberror . dbi_error ();

        // Send mail notification if enabled.
        // TODO:  Move this code into a function...
        if ( $EXTERNAL_NOTIFICATIONS == 'Y' && $SEND_EMAIL != 'N' &&
          strlen ( $ext_emails[$i] ) > 0 ) {
          if ( ( ! $newevent && isset ( $EXTERNAL_UPDATES ) &&
            $EXTERNAL_UPDATES == 'Y' ) || $newevent ) {
            $fmtdate = ( $timetype == 'T'
              ? date ( 'Ymd', $eventstart ) : gmdate ( 'Ymd', $eventstart ) );
            // Strip [\d] from duplicate Names before emailing.
            $ext_names[$i] = trim ( preg_replace ( '/\[[\d]]/', '', $ext_names[$i] ) );
            $msg = str_replace ( 'XXX', $ext_names[$i], $helloStr ) . "\n\n"
             . str_replace ( 'XXX', $login_fullname,
              ( $newevent ? $newAppStr : $updAppStr ) ) . "\n"
             . str_replace ( 'XXX', $name, $subjStr ) . "\n\n"
             . str_replace ( 'XXX', $description, $descStr ) . "\n\n"
             . str_replace ( 'XXX', date_to_str ( $fmtdate ), $dateStr ) . "\n"
             . ( $timetype == 'T' ? str_replace ( 'XXX',
                display_time ( '',
                  ( ! empty ( $GENERAL_USE_GMT ) && $GENERAL_USE_GMT == 'Y'
                    ? 3 // Do not apply TZ offset & display TZID, which is GMT.
                    : 6 // Display time in server's timezone.
                    ), $eventstart ), $timeStr ) : '' )
            // Add Site Extra Date if permitted.
            . $extra_email_data;
            // Don't send HTML to external adresses.
            // Always attach iCalendar file to external users
            $mail->WC_Send ( $login_fullname, $ext_emails[$i],
              $ext_names[$i], $name, $msg, 'N', $from, $id );
          }
        }
      }
    }
  } //end external mail
} //end empty error
// If we were editing this event, then go back to the last view (day, month, week).
// If this is a new event,
// then go to the preferred view for the date range where this event was added.
if ( empty ( $error ) && empty ( $mailerError ) ) {
  $return_view = get_last_view ();
  if ( ! empty ( $return_view ) )
    do_redirect ( $return_view );
  else {
    $xdate = sprintf ( "%04d%02d%02d", $year, $month, $day );
    $user_args = ( empty ( $user ) ? '' : 'user=' . $user );
    send_to_preferred_view ( $xdate, $user_args );
  }
}

if ( ! empty ( $conflicts ) ) {
  print_header ();

  ob_start ();
  echo '
    <h2>' . translate ( 'Scheduling Conflict' ) . '</h2>
    ' . translate ( 'Your suggested time of' ) . '
    <span class="bold">';

  if ( $timetype == 'A' )
    etranslate ( 'All day event' );
  else {
    $time = sprintf ( "%d%02d00", $entry_hour, $entry_minute );
    // Pass the adjusted timestamp in case the date changed due to GMT offset.
    echo display_time ( '', 0, $eventstart );
    if ( $duration > 0 )
      echo '-' . display_time ( '', 0, $eventstart + ( $duration * 60 ) );
  }

  echo '</span>
    ' . translate ( 'conflicts with the following existing calendar entries' ) . ':
    <ul>' . $conflicts . '
    </ul>
    ' // User can confirm conflicts.
  . '<form name="confirm" method="post">';
  foreach ( $_POST as $xkey => $xval ) {
    if ( is_array ( $xval ) ) {
      $xkey .= "[]";
      foreach ( $xval as $ykey => $yval ) {
        if ( get_magic_quotes_gpc () )
          $yval = stripslashes ( $yval );
        // $yval = htmlentities ( $yval );
        echo '
      <input type="hidden" name="' . $xkey . '" value="' . $yval . '" />';
      }
    } else {
      if ( get_magic_quotes_gpc () )
        $xval = stripslashes ( $xval );
      // $xval = htmlentities ( $xval );
      echo '
      <input type="hidden" name="' . $xkey . '" value="' . $xval . '" />';
    }
  }

  echo '
      <table>
        <tr>'
  // Allow them to override a conflict if server settings allow it.
  . ( ! empty ( $ALLOW_CONFLICT_OVERRIDE ) && $ALLOW_CONFLICT_OVERRIDE == 'Y' ? '
          <td><input type="submit" name="confirm_conflicts" value="'
     . translate ( 'Save' ) . '" /></td>' : '' ) . '
          <td><input type="button" value="' . translate ( 'Cancel' )
   . '" onclick="history.back()" /><td>
        </tr>
      </table>
    </form>';

  ob_end_flush ();
} else
  // Process errors.
  $mail->MailError ( $mailerError, $error );

?>

Added edit_layer.php.































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
/* $Id: edit_layer.php,v 1.57.2.4 2008/03/11 13:57:24 cknudsen Exp $ */
include_once 'includes/init.php';

if ( $ALLOW_VIEW_OTHER != 'Y' ) {
  print_header ();
  echo print_not_auth (7) . print_trailer ();
  exit;
}

$layer_user = $login;
$updating_public = false;
$public = getValue ( 'public', '[01]' );

if ( $is_admin && $public == '1' && $PUBLIC_ACCESS == 'Y' ) {
  $layer_user = '__public__';
  $updating_public = true;
}

load_user_layers ( $layer_user, 1 );

$checked = 'checked="checked"';
$color = ( ! empty ( $layers[$id]['cal_color'] )
  ? $layers[$id]['cal_color'] : '#000' );
$helpStr = translate ( 'Help' );
$hiddenStr = ( $updating_public ? '
      <input type="hidden" name="public" value="1" />' : '' );
$publicStr = ( $updating_public ? translate ( $PUBLIC_ACCESS_FULLNAME ) . ' ' : '' );
$titleStr = ( empty ( $layers[$id]['cal_layeruser'] )
  ? translate ( 'Add Layer' ) : translate ( 'Edit Layer' ) );

print_header ( array ( 'js/edit_layer.php', 'js/visible.php' ) );

ob_start ();

echo <<<EOT
    <h2>{$publicStr}{$titleStr}&nbsp;
      <img src="images/help.gif" alt="{$helpStr}" class="help"
onclick="window.open( 'help_layers.php','cal_help','dependent,menubar,scrollbars,height=400,width=400,innerHeight=420,outerWidth=420' );" />
    </h2>
    <form action="edit_layer_handler.php" method="post"
      onsubmit="return valid_form( this );" name="prefform">{$hiddenStr}
      <table cellspacing="2" cellpadding="3">
EOT;

if ( $single_user == 'N' ) {
  $otherlist = $userlist = get_my_users ( '', 'view' );
  if ( $NONUSER_ENABLED == 'Y' ) {
    // Restrict NUC list if groups are enabled.
    $nonusers = get_my_nonusers ( $login, true, 'view' );
    $userlist = ( $NONUSER_AT_TOP == 'Y'
      ? array_merge ( $nonusers, $userlist )
      : array_merge ( $userlist, $nonusers ) );
  }
  if ( $REMOTES_ENABLED == 'Y' ) {
    $remotes = get_nonuser_cals ( $login, true );
    $userlist = ( $NONUSER_AT_TOP == 'Y'
      ? array_merge ( $remotes, $userlist )
      : array_merge ( $userlist, $remotes ) );
  }

  $num_users = $osize = $size = 0;
  $others = $users = '';

  for ( $i = 0, $cnt = count ( $userlist ); $i < $cnt; $i++ ) {
    if ( $userlist[$i]['cal_login'] != $layer_user ) {
      $size++;
      $users .= '
              <option value="' . $userlist[$i]['cal_login'] . '"'
       . ( ! empty ( $layers[$id]['cal_layeruser'] ) &&
        $layers[$id]['cal_layeruser'] == $userlist[$i]['cal_login']
        ? ' selected="selected"' : '' )
       . '>' . $userlist[$i]['cal_fullname'] . '</option>';
    }
  }

  for ( $i = 0, $cnt = count ( $otherlist ); $i < $cnt; $i++ ) {
    if ( $otherlist[$i]['cal_login'] != $layer_user ) {
      $osize++;
      $others .= '
              <option value="' . $otherlist[$i]['cal_login'] . '">'
       . $otherlist[$i]['cal_fullname'] . '</option>';
    }
  }

  if ( $size > 50 )
    $size = 15;
  elseif ( $size > 5 )
    $size = 5;

  if ( $osize > 50 )
    $osize = 15;
  elseif ( $osize > 5 )
    $osize = 5;

  if ( $size > 0 ) {
    $sourceStr = translate ( 'Source' );
    echo <<<EOT
        <tr>
          <td class="aligntop"><label for="layeruser">{$sourceStr}:</label></td>
          <td colspan="3">
            <select name="layeruser" id="layeruser" size="1">{$users}
            </select>
          </td>
        </tr>

EOT;
  }
}
$colorHtmlStr = print_color_input_html ( 'layercolor', translate ( 'Color' ),
  $color );
$duplicatesStr = translate ( 'Duplicates' );
$dupsChecked = ( ! empty ( $layers[$id]['cal_dups'] ) && $layers[$id]['cal_dups'] == 'Y'
  ? $checked : '' );
$showStr = translate ( 'Show layer events that are the same as your own' );

echo <<<EOT
        <tr>
          <td>{$colorHtmlStr}</td>
        </tr>
        <tr>
          <td class="bold">{$duplicatesStr}:</td>
          <td colspan="3"><label>
           <input type="checkbox" name="dups" value="Y" {$dupsChecked}/>&nbsp;
           {$showStr}?</label>
         </td>
        </tr>

EOT;
// If admin and adding a new layer, add ability to select other users.
if ( $is_admin && empty ( $layers[$id]['cal_layeruser'] ) && empty ( $public ) ) {
  $addStr = translate ( 'Add to Others' );
  $addmyStr = translate ( 'Add to My Calendar' );
  echo <<<EOT
        <tr>
          <td class="bold">{$addmyStr}:</td>
          <td colspan="3"><input type="checkbox" name="is_mine" {$checked}
            onclick="show_others();" /></td>
        </tr>
        <tr id="others" style="visibility: hidden;">
          <td class="aligntop"><label for="cal_login">{$addStr}:</label></td>
          <td colspan="3">
            <select name="cal_login[]" id="cal_login" size="{$osize}"
              multiple="multiple">{$others}
            </select>
          </td>
        </tr>

EOT;
}
$saveStr = translate ( 'Save' );
// If a layer already exists put a 'Delete Layer' link.
$deleteStr = ( ! empty ( $layers[$id]['cal_layeruser'] ) ? '&nbsp;&nbsp;&nbsp;
            <input type="button" value="' . translate ( 'Delete layer' )
   . '" onclick="return deleteLayer( \'del_layer.php?id=' . $id
   . ( $updating_public ? '&amp;public=1' : '' ) . '\')" />' : '' );
$hiddenStr = ( ! empty ( $layers[$id]['cal_layeruser'] ) ? '
      <input type="hidden" name="id" value="' . $id . '" />' : '' );

echo <<<EOT
        <tr>
          <td colspan="4">
            <input type="submit" value="{$saveStr}" />{$deleteStr}
          </td>
        </tr>
      </table>
      {$hiddenStr}
    </form>
EOT;

ob_end_flush ();

echo print_trailer ();

?>

Added edit_layer_handler.php.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php
/* $Id: edit_layer_handler.php,v 1.31.2.4 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();

$error = '';

if ( $ALLOW_VIEW_OTHER != 'Y' )
  $error = print_not_auth (7);

$public = getPostValue ( 'public' );
$layeruser = getPostValue ( 'layeruser' );
$layercolor = getPostValue ( 'layercolor' );
$dups = getPostValue ( 'dups' );
$is_mine = getPostValue ( 'is_mine' );
$cal_login = getPostValue ( 'cal_login' );
$id = getPostValue ( 'id' );

if ( empty ( $dups ) )
  $dups = 'N';

$updating_public = false;
if ( $is_admin && ! empty ( $public ) && $PUBLIC_ACCESS == 'Y' ) {
  $updating_public = true;
  save_layer ( '__public__', $layeruser, $layercolor, $dups, $id );
} else
if ( empty ( $cal_login ) )
  save_layer ( $login, $layeruser, $layercolor, $dups, $id );
else {
  // See if we are processing multiple layer_users as admin.
  if ( $is_admin && ! empty ( $cal_login ) ) {
    for ( $i = 0, $cnt = count ( $cal_login ); $i < $cnt; $i++ ) {
      save_layer ( $cal_login[$i], $layeruser, $layercolor, 'N', $id );
    }
  }
}

function save_layer ( $layer_user, $layeruser, $layercolor, $dups, $id ) {
  global $error, $layers;

  if ( $layer_user == $layeruser )
    $error = translate ( 'You cannot create a layer for yourself.' );

  load_user_layers ( $layer_user, 1 );

  if ( ! empty ( $layeruser ) && $error == '' ) {
    // Existing layer entry.
    if ( ! empty ( $layers[$id]['cal_layeruser'] ) ) {
      // Update existing layer entry for this user.
      $layerid = $layers[$id]['cal_layerid'];

      dbi_execute ( 'UPDATE webcal_user_layers SET cal_layeruser = ?,
        cal_color = ?, cal_dups = ? WHERE cal_layerid = ?',
        array ( $layeruser, $layercolor, $dups, $layerid ) );
    } else {
      // New layer entry.
      // Check for existing layer for user. Can only have one layer per user.
      $res = dbi_execute ( 'SELECT COUNT( cal_layerid ) FROM webcal_user_layers
        WHERE cal_login = ? AND cal_layeruser = ?',
        array ( $layer_user, $layeruser ) );
      if ( $res ) {
        $row = dbi_fetch_row ( $res );
        if ( $row[0] > 0 )
          $error = translate ( 'You can only create one layer for each user.' );

        dbi_free_result ( $res );
      }
      if ( $error == '' ) {
        $res =
        dbi_execute ( 'SELECT MAX( cal_layerid ) FROM webcal_user_layers' );
        if ( $res ) {
          $row = dbi_fetch_row ( $res );
          $layerid = $row[0] + 1;
        } else
          $layerid = 1;

        dbi_execute ( 'INSERT INTO webcal_user_layers ( cal_layerid, cal_login,
          cal_layeruser, cal_color, cal_dups ) VALUES ( ?, ?, ?, ?, ? )',
          array ( $layerid, $layer_user, $layeruser, $layercolor, $dups ) );
      }
    }
  }
}

// We don't want to throw errors if doing a multiple save.
if ( $error == '' || ! empty ( $cal_login ) ) {
  do_redirect ( 'layers.php' . ( $updating_public ? '?public=1' : '' ) );
  exit;
}

print_header ();
echo print_error ( $error ) . print_trailer ();

?>

Added edit_nonusers.php.















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
/* $Id: edit_nonusers.php,v 1.23.2.6 2008/05/23 14:14:11 umcesrjones Exp $ */
include_once 'includes/init.php';
print_header ( array ( 'js/edit_nonuser.php/false' ),
  '', '', true, '', true, false );

if ( ! $is_admin ) {
  echo print_not_auth ( 3, true ) . '
  </body>
</html>';
  exit;
}
if ( ! $NONUSER_PREFIX ) {
  echo print_error_header () . translate ( 'NONUSER_PREFIX not set' ) . '.
  </body>
</html>';
  exit;
}
$add = getValue ( 'add' );
$nid = getValue ( 'nid' );

// Adding/Editing nonuser calendar.
if ( ( ( $add == '1' ) || ( ! empty ( $nid ) ) ) && empty ( $error ) ) {
  $userlist = user_get_users ();
  $button = translate ( 'Add', true );
    $buttonAction = 'Add';
  $nid = clean_html ( $nid );

  if ( ! empty ( $nid ) ) {
    nonuser_load_variables ( $nid, 'nonusertemp_' );
    $id_display = $nid . '
      <input type="hidden" name="nid" value="' . $nid . '" />';
    $button = translate ( 'Save', true );
        $buttonAction = 'Save';
    //$nonusertemp_login = substr ( $nonusertemp_login,
   //   strlen ( $NONUSER_PREFIX ) );
  } else
    $id_display = '
      <input type="text" name="nid" id="calid" size="20" '
     . 'onchange="check_name();" maxlength="20" /> '
     . translate ( 'word characters only' );

  ob_start ();

  echo '
    <form action="edit_nonusers_handler.php" name="editnonuser" method="post" '
   . 'onsubmit="return valid_form( this );">'
   . ( empty ( $nonusertemp_admin ) ? '' : '
      <input type="hidden" name="old_admin" value="'
     . $nonusertemp_admin . '" />' ) . '
      <h2>' . ( empty ( $nid )
    ? translate ( 'Add User' ) : translate ( 'Edit User' ) ) . '</h2>
      <table>
        <tr>
          <td><label for="calid">' . translate ( 'Calendar ID' )
   . ':</label></td>
          <td>' . $id_display . '</td>
        </tr>
        <tr>
          <td><label for="nfirstname">' . translate ( 'First Name' )
   . ':</label></td>
          <td><input type="text" name="nfirstname" id="nfirstname" size="20" '
   . 'maxlength="25" value="'
   . ( empty ( $nonusertemp_firstname )
    ? '' : htmlspecialchars ( $nonusertemp_firstname ) ) . '" /></td>
        </tr>
        <tr>
          <td><label for="nlastname">' . translate ( 'Last Name' )
   . ':</label></td>
          <td><input type="text" name="nlastname" id="nlastname" size="20" '
   . 'maxlength="25" value="'
   . ( empty ( $nonusertemp_lastname )
    ? '' : htmlspecialchars ( $nonusertemp_lastname ) ) . '" /></td>
        </tr>
        <tr>
          <td><label for="nadmin">' . translate ( 'Admin' ) . ':</label></td>
          <td>
            <select name="nadmin" id="nadmin">';

  for ( $i = 0, $cnt = count ( $userlist ); $i < $cnt; $i++ ) {
    echo '
              <option value="' . $userlist[$i]['cal_login'] . '"'
     . ( ! empty ( $nonusertemp_admin ) &&
      $nonusertemp_admin == $userlist[$i]['cal_login']
      ? ' selected="selected"' : '' ) . '>' . $userlist[$i]['cal_fullname']
     . '</option>';
  }

  echo '
            </select>
          </td>
        </tr>';

  if ( ! $use_http_auth ) {
    echo '
        <tr>
          <td valign="top"><label for="ispublic">'
     . translate ( 'Is public calendar' ) . ':</td>
          <td>
            <input type="radio" name="ispublic" value="Y" '
     . ( ! empty ( $nonusertemp_is_public ) && $nonusertemp_is_public == 'Y'
      ? ' checked="checked"' : '' ) . ' /> ' . translate ( 'Yes' )
     . '&nbsp;&nbsp;<input type="radio" name="ispublic" value="N" '
     . ( empty ( $nonusertemp_is_public ) || $nonusertemp_is_public != 'Y'
      ? ' checked="checked"' : '' ) . ' /> ' . translate ( 'No' ) . '<br />';

    if ( ! empty ( $nonusertemp_login ) ) {
      $nu_url = $SERVER_URL . 'nulogin.php?login=' . $nonusertemp_login;
      echo  $nu_url;
    }

    echo '
          </td>
        </tr>';
  }

  echo '
      </table><br />
      <input type="submit" name="' . $buttonAction 
            . '" value="' . $button . '" />'
   . ( empty ( $nid ) ? '' : '
      <input type="submit" name="delete" value="' . translate ( 'Delete')
     . '" onclick="return confirm( \''
     . str_replace ( 'XXX', translate ( 'entry' ),
      translate ( 'Are you sure you want to delete this XXX?' ) )
     . '\')" />' ) . '
    </form>
    ';
}

ob_end_flush ();

echo print_trailer ( false, true, true );

?>

Added edit_nonusers_handler.php.



























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
/* $Id: edit_nonusers_handler.php,v 1.28.2.7 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
require_valide_referring_url ();
load_user_layers ();

if ( ! $is_admin ) {
  echo print_not_auth ( 3, true );
  echo "</body>\n</html>";
  exit;
}
$error = '';
$save = getPostValue ( 'Save' );
$add = getPostValue ( 'Add' );
$delete = getPostValue ( 'delete' );
$nid = getPostValue ( 'nid' );
$nfirstname = getPostValue ( 'nfirstname' );
$nlastname = getPostValue ( 'nlastname' );
$nadmin = getPostValue ( 'nadmin' );
$old_admin = getPostValue ( 'old_admin' );
$ispublic = getPostValue ( 'ispublic' );
if ( empty ( $ispublic ) ) $ispublic = 'N';

if ( ! empty ( $delete ) ) {
  // delete this nonuser calendar

  // Get event ids for all events this user is a participant
  $events = get_users_event_ids ( $nid );

  // Now count number of participants in each event...
  // If just 1, then save id to be deleted
  $delete_em = array ();
  for ( $i = 0, $cnt = count ( $events ); $i < $cnt; $i++ ) {
    $res = dbi_execute ( 'SELECT COUNT( * )
      FROM webcal_entry_user WHERE cal_id = ?', array ( $events[$i] ) );
    if ( $res ) {
      if ( $row = dbi_fetch_row ( $res ) ) {
        if ( $row[0] == 1 )
   $delete_em[] = $events[$i];
      }
      dbi_free_result ( $res );
    }
  }
  // Now delete events that were just for this user
  for ( $i = 0, $cnt = count ( $delete_em ); $i < $cnt; $i++ ) {
    dbi_execute ( 'DELETE FROM webcal_entry_repeats WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_repeats_not WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_log WHERE cal_entry_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_import_data WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_site_extras WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_ext_user WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_reminders WHERE cal_id =? ',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_blob WHERE cal_id = ?',
     array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
  }

  // Delete user participation from events
  dbi_execute ( 'DELETE FROM webcal_entry_user WHERE cal_login = ?',
    array ( $nid ) );

  // Delete any layers other users may have that point to this user.
  dbi_execute ( 'DELETE FROM webcal_user_layers WHERE cal_layeruser = ?',
    array ( $nid ) );

  // Delete any UAC calendar access entries for this  user.
  dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
    OR cal_other_user = ?', array ( $nid, $nid ) );

  // Delete any UAC function access entries for this  user.
  dbi_execute ( 'DELETE FROM webcal_access_function WHERE cal_login = ?',
    array ( $nid ) );

  // Delete user
  if ( ! dbi_execute ( 'DELETE FROM webcal_nonuser_cals WHERE cal_login = ?',
    array ( $nid ) ) )
    $error = db_error ();
		
} else if ( ! empty ( $save ) ) {
  // Updating
  $query_params = array ();
  $sql = 'UPDATE webcal_nonuser_cals SET ';
  if ($nlastname) {
    $sql .= ' cal_lastname = ?, ';
    $query_params[] = $nlastname;
  }
  if ($nfirstname) {
    $sql .= ' cal_firstname = ?, ';
    $query_params[] = $nfirstname;
  }
  if ( $ispublic ) {
    $sql .= ' cal_is_public = ?, ';
    $query_params[] = $ispublic;
  }

  $query_params[] = $nadmin;
  $query_params[] = $nid;

  if ( ! dbi_execute ( $sql . 'cal_admin = ? WHERE cal_login = ?',
    $query_params ) )
    $error = db_error ();
} else if ( ! empty ( $add ) ){
  // Adding
  if ( preg_match ( '/^[\w]+$/', $nid ) ) {
    $nid = $NONUSER_PREFIX.$nid;
    if ( ! dbi_execute ( 'INSERT INTO webcal_nonuser_cals ( cal_login,
      cal_firstname, cal_lastname, cal_admin, cal_is_public )
      VALUES ( ?, ?, ?, ?, ? )',
      array ( $nid, $nfirstname, $nlastname, $nadmin, $ispublic ) ) ) {
      $error = db_error ();
    }
  } else {
    $error = translate ( 'Calendar ID' ).' '.translate ( 'word characters only' ).'.';
  }
  //Add entry in UAC access table for new admin and remove for of admin
  //first delete any record for this user/nuc combo
  dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
    AND cal_other_user = ?', array ( $nadmin, $nid ) );
  if ( ! dbi_execute ( 'INSERT INTO webcal_access_user ( cal_login,
    cal_other_user, cal_can_view, cal_can_edit, cal_can_approve, cal_can_invite,
    cal_can_email, cal_see_time_only ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )',
    array ( $nadmin, $nid, 511, 511, 511, 'Y', 'Y', 'N' ) ) ) {
    die_miserable_death ( translate ( 'Database error' ) . ': ' . dbi_error () );
  }
  // Delete old admin...
  //TODO Make this an optional step
  if ( ! empty ( $old_admin ) )
    dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
      AND cal_other_user = ?', array ( $old_admin, $nid ) );
}

echo error_check('users.php?tab=nonusers', false);
?>

Added edit_remotes.php.





























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<?php
/* Allows a user to specify a remote calendar by URL that can be imported
 * manually into the NUC calendar specified. The user will also be allowed to
 * create a layer to display this calendar on top of their own calendar.
 *
 * @author Ray Jones <rjones@umces.edu>
 * @copyright Craig Knudsen, <cknudsen@cknudsen.com>, http://www.k5n.us/cknudsen
 * @license http://www.gnu.org/licenses/gpl.html GNU GPL
 * @version $Id: edit_remotes.php,v 1.17.2.4 2007/11/12 20:47:48 umcesrjones Exp $
 * @package WebCalendar
 * @subpackage Edit Remotes
 *
 * Security
 * $REMOTES_ENABLED must be enabled under System Settings and if
 * if UAC is enabled, then the user must be allowed to ACCESS_IMPORT.
*/
include_once 'includes/init.php';
print_header ( array ( 'js/edit_remotes.php/false', 'js/visible.php' ),
  '', '', true );

$error = '';

if ( ! $NONUSER_PREFIX )
  $error = translate ( 'NONUSER_PREFIX not set' );

if ( $REMOTES_ENABLED != 'Y' || ( access_is_enabled () && !
      access_can_access_function ( ACCESS_IMPORT ) ) )
  $error = print_not_auth (11);

if ( $error ) {
  echo print_error ( $error ) . '
  </body>
</html>';
  exit;
}
$add = getValue ( 'add' );
$nid = getValue ( 'nid' );

// Adding/Editing remote calendar.
if ( ( $add == '1' || ! empty ( $nid ) ) && empty ( $error ) ) {
  $userlist = get_nonuser_cals ( $login, true );

  if ( empty ( $nid ) ) {
    $id_display = '<input type="text" name="nid" id="nid" size="20" '
     . 'maxlength="20" onchange="check_name();" /> '
     . translate ( 'word characters only' );
    $lableStr = translate ( 'Add Remote Calendar' );
  } else {
    $nid = clean_html ( $nid );
    nonuser_load_variables ( $nid, 'remotestemp_' );

    $button = translate ( 'Save' );
		$buttonAction = 'Save';
    $id_display = $nid . ' <input type="hidden" name="nid" id="nid" value="'
     . $nid . '" />';
    $lableStr = translate ( 'Edit Remote Calendar' );
    $remotestemp_login = substr ( $remotestemp_login, strlen ( $NONUSER_PREFIX ) );
  }

  $button = translate ( 'Add' );
	$buttonAction = 'Add';
  $calIdStr = translate ( 'Calendar ID' );
  $colorStr = translate ( 'Color' );
  $confirmStr = str_replace ( 'XXX', translate ( 'entry' ),
    translate ( 'Are you sure you want to delete this XXX?' ) );
  $createLayerStr = translate ( 'Create Layer' );
  $deleteStr = translate ( 'Delete' );
  $firstNameStr = translate ( 'First Name' );
  $lastNameStr = translate ( 'Last Name' );
  $reloadStr = translate ( 'Reload' );
  $requiredStr = translate ( 'Required to View Remote Calendar' );
  $selectStr = translate ( 'Select' );
  $urlStr = translate ( 'URL' );

  $firstNameValue = ( empty ( $remotestemp_firstname )
    ? '' : htmlspecialchars ( $remotestemp_firstname ) );
  $lastNameValue = ( empty ( $remotestemp_lastname )
    ? '' : htmlspecialchars ( $remotestemp_lastname ) );
  $urlValue = ( empty ( $remotestemp_url )
    ? '' : htmlspecialchars ( $remotestemp_url ) );

  echo <<<EOT
    <h2>{$lableStr}</h2>
    <form action="edit_remotes_handler.php" method="post" name="prefform"
      onsubmit="return valid_form( this );">
      <table cellspacing="0" cellpadding="2">
        <tr>
          <td><label for="calid">{$calIdStr}:</label></td>
          <td colspan="3">{$id_display}</td>
        </tr>
        <tr>
          <td><label for="nfirstname">{$firstNameStr}:</label></td>
          <td colspan="3"><input type="text" name="nfirstname" id="nfirstname"
            size="20" maxlength="25" value="{$firstNameValue}" /></td>
        </tr>
        <tr>
          <td><label for="nlastname">{$lastNameStr}:</label></td>
          <td colspan="3"><input type="text" name="nlastname" id="nlastname"
            size="20" maxlength="25" value="{$lastNameValue}" /></td>
        </tr>
        <tr>
          <td><label for="nurl">{$urlStr}:</label></td>
          <td colspan="3"><input type="text" name="nurl" id="nurl" size="75"
            maxlength="255" value="{$urlValue}" /></td>
        </tr>
EOT;
  if ( empty ( $nid ) ) {
    echo <<<EOT
        <tr>
          <td><label for="nlayer">{$createLayerStr}:</label></td>
          <td colspan="3">
            <input type="hidden" name="reload" id="reload" value="true" />
            <input type="checkbox" name="nlayer" id="nlayer" value="Y"
              onchange="toggle_layercolor();" />{$requiredStr}
          </td>
        </tr>
        <tr id="nlayercolor" style="visibility:hidden" >
          <td>
EOT;
    echo print_color_input_html ( 'layercolor', $colorStr, '#000000' ) . '
          </td>
        </tr>';
  }
  echo <<<EOT
      </table>
      <input type="hidden" name="nadmin" id="nadmin" value="{$login}" />
      <input type="submit" name="{$buttonAction}" value="{$button}" />
EOT;

  if ( ! empty ( $nid ) )
    echo <<<EOT
      <input type="submit" name="delete" value="{$deleteStr}"
        onclick="return confirm( '{$confirmStr}' )" />
      <input type="submit" name="reload" value="{$reloadStr}" />
EOT;

  echo '
    </form>';
}
echo print_trailer ( false, true, true );

?>

Added edit_remotes_handler.php.











































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<?php
/* $Id: edit_remotes_handler.php,v 1.16.2.6 2012/02/28 02:07:45 cknudsen Exp $ */
include_once 'includes/init.php';
include_once 'includes/xcal.php';
require_valide_referring_url ();

// Only available in php 5.x Used for hCalendar parsing.
if ( function_exists ( 'simplexml_load_string' ) )
  require_once 'includes/classes/hKit/hkit.class.php';

$error = '';
$layer_found = false;

$save = getPostValue ( 'Save' );
$add = getPostValue ( 'Add' );
$delete = getPostValue ( 'delete' );
$reload = getPostValue ( 'reload' );
$nid = getPostValue ( 'nid' );
$nfirstname = getPostValue ( 'nfirstname' );
$nlastname = getPostValue ( 'nlastname' );
$nadmin = getPostValue ( 'nadmin' );
$nurl = getPostValue ( 'nurl' );
$reload = getPostValue ( 'reload' );
$nlayer = getPostValue ( 'nlayer' );
$nlayercolor = getPostValue ( 'layercolor' );

if ( ! empty ( $delete ) ) {
  // Delete events from this remote calendar.
  delete_events ( $nid );

  // Delete any layers other users may have that point to this user.
  dbi_execute ( 'DELETE FROM webcal_user_layers WHERE cal_layeruser = ?',
    array ( $nid ) );

  // Delete any UAC calendar access entries for this  user.
  dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
    OR cal_other_user = ?', array ( $nid, $nid ) );

  // Delete any UAC function access entries for this  user.
  dbi_execute ( 'DELETE FROM webcal_access_function WHERE cal_login = ?',
    array ( $nid ) );

  // Delete user.
  if ( ! dbi_execute ( 'DELETE FROM webcal_nonuser_cals WHERE cal_login = ?',
      array ( $nid ) ) )
    $error = db_error ();
} else {
  if ( ! empty ( $nid ) && ! empty ( $save ) ) {
    // Updating
    $query_params = array ();
    $sql = 'UPDATE webcal_nonuser_cals SET ';
    if ( $nlastname ) {
      $sql .= ' cal_lastname = ?, ';
      $query_params[] = $nlastname;
    }
    if ( $nfirstname ) {
      $sql .= ' cal_firstname = ?, ';
      $query_params[] = $nfirstname;
    }
    $sql .= ' cal_url = ?, cal_is_public = ?, cal_admin = ?
      WHERE cal_login = ?';
    $query_params[] = $nurl;
    $query_params[] = 'N';
    $query_params[] = $nadmin;
    $query_params[] = $nid;

    if ( ! dbi_execute ( $sql, $query_params ) )
      $error = db_error ();
  } else
  if ( ! empty ( $add ) ) {
    // Adding
    if ( preg_match ( '/^[\w]+$/', $nid ) ) {
      $nid = $NONUSER_PREFIX . $nid;
      if ( ! dbi_execute ( 'INSERT INTO webcal_nonuser_cals ( cal_login,
        cal_firstname, cal_lastname, cal_admin, cal_is_public, cal_url )
        VALUES ( ?, ?, ?, ?, ?, ? )',
          array ( $nid, $nfirstname, $nlastname, $nadmin, 'N', $nurl ) ) )
        $error = db_error ();
    } else
      $error = translate ( 'Calendar ID' ) . ' '
       . translate ( 'word characters only' ) . '.';

    // Add new layer if requested.
    if ( ! empty ( $nlayer ) && $nlayer == 'Y' ) {
      $res = dbi_execute ( 'SELECT MAX( cal_layerid ) FROM webcal_user_layers' );
      $layerid = 1;
      if ( $res ) {
        $row = dbi_fetch_row ( $res );
        $layerid += $row[0];
      }

      dbi_execute ( 'INSERT INTO webcal_user_layers ( cal_layerid, cal_login,
        cal_layeruser, cal_color, cal_dups ) VALUES ( ?, ?, ?, ?, ? )',
        array ( $layerid, $login, $nid, $layercolor, 'N' ) );
      $layer_found = true;
    }
  }
  // Add entry in UAC access table for new admin and remove for old admin.
  // First delete any record for this user/nuc combo.
  dbi_execute ( 'DELETE FROM webcal_access_user WHERE cal_login = ?
    AND cal_other_user = ?', array ( $nadmin, $nid ) );
  if ( ! dbi_execute ( 'INSERT INTO webcal_access_user ( cal_login,
    cal_other_user, cal_can_view, cal_can_edit, cal_can_approve, cal_can_invite,
    cal_can_email, cal_see_time_only ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? )',
      array ( $nadmin, $nid, 511, 511, 511, 'Y', 'Y', 'N' ) ) )
    die_miserable_death ( translate ( 'Database error' ) . ': '
       . dbi_error () );
}

if ( ! empty ( $reload ) ) {
  $data = array ();
  $calUser = $nid;
  $overwrite = true;
  $type = 'remoteics';
  // We will check ics first.
  $data = parse_ical ( $nurl, $type );
  // TODO it may be a vcs file.
  // if ( count ( $data ) == 0 ) {
  // $data = parse_vcal ( $nurl );
  // }
  // We may be processing an hCalendar.
  // $data sometimes has a count of 1 but is not a valid array.
  if ( ( count ( $data ) == 0 || ! isset ( $data[0] ) ) &&
      function_exists ( 'simplexml_load_string' ) ) {
    $h = new hKit;
    $h->tidy_mode = 'proxy';
    $result = $h->getByURL ( 'hcal', $nurl );
    $type = 'hcal';
    $data = parse_hcal ( $result, $type );
  }

  $errorStr = '<br /><br />
    <b>' . translate ( 'Error' ) . ':</b> ';

  print_header ( '', '', '', true, false, true );
  if ( count ( $data ) && empty ( $errormsg ) ) {
    // Delete existing events.
    delete_events ( $nid );
    // Import new events.
    import_data ( $data, $overwrite, $type );
    echo '
    <p>' . translate ( 'Import Results' ) . '</p><br /><br />
    ' . translate ( 'Events successfully imported' ) . ': ' . $count_suc
     . '<br />';
    if ( $layer_found == false ) { // We may have just added layer.
      load_user_layers ();
      foreach ( $layers as $layer ) {
        if ( $layer['cal_layeruser'] == $nid )
          $layer_found = true;
      }
    }
    if ( $layer_found == false )
      echo '
    <p>' . translate ( 'Create a new layer to view this calendar' ) . '.</p>';
  } elseif ( ! empty ( $errormsg ) ) {
    echo '
    ' . translate ( 'Errors' ) . ': ' . $error_num . '<br /><br />
    ' . $errorStr . $errormsg . '<br />';
  } else {
    echo $errorStr .
    translate ( 'There was an error parsing the import file or no events were returned' )
     . '.<br />';
  }
  echo print_trailer ( false, true, true );
}

function delete_events ( $nid ) {
  // Get event ids for all events this user is a participant.
  $events = get_users_event_ids ( $nid );

  // Now count number of participants in each event...
  // If just 1, then save id to be deleted.
  $delete_em = array ();
  for ( $i = 0, $cnt = count ( $events ); $i < $cnt; $i++ ) {
    $res = dbi_execute ( 'SELECT COUNT( * ) FROM webcal_entry_user
      WHERE cal_id = ?', array ( $events[$i] ) );
    if ( $res ) {
	  $row = dbi_fetch_row ( $res );
      if ( ! empty ( $row ) && $row[0] == 1 )
        $delete_em[] = $events[$i];

      dbi_free_result ( $res );
    }
  }
  // Now delete events that were just for this user.
  for ( $i = 0, $cnt = count ( $delete_em ); $i < $cnt; $i++ ) {
    dbi_execute ( 'DELETE FROM webcal_entry_repeats WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_repeats_not WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_log WHERE cal_entry_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_import_data WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_site_extras WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry_ext_user WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_reminders WHERE cal_id =? ',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_blob WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
    dbi_execute ( 'DELETE FROM webcal_entry WHERE cal_id = ?',
      array ( $delete_em[$i] ) );
  }
  // Delete user participation from events.
  dbi_execute ( 'DELETE FROM webcal_entry_user WHERE cal_login = ?',
    array ( $nid ) );
}

echo error_check ( 'users.php?tab=remotes', false );

?>

Added edit_report.php.



































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<?php
/* Presents a HTML form to add or edit a report.
 *
 * Input Parameters:
 * - <var>report_id</var> (optional) - the report id of the report to edit. If
 *   blank, user is adding a new report.
 * - <var>public</var> (optional) - If set to '1' and user is an admin user,
 *   then we are creating a report for the public user.
 *
 * @author Craig Knudsen <cknudsen@cknudsen.com>
 * @copyright Craig Knudsen, <cknudsen@cknudsen.com>, http://www.k5n.us/cknudsen
 * @license http://www.gnu.org/licenses/gpl.html GNU GPL
 * @version $Id: edit_report.php,v 1.58.2.4 2013/01/24 21:10:19 cknudsen Exp $
 * @package WebCalendar
 * @subpackage Reports
 */

/* Security:
 * If system setting $REPORTS_ENABLED is set to anything other than 'Y',
 * then don't allow access to this page.
 * If $ALLOW_VIEW_OTHER is 'N', then do not allow selection of participants.
 * Only report creator (cal_login in webcal_report), or an admin user,
 * can edit/delete report.
 */

include_once 'includes/init.php';
load_user_categories ();

$adding_report = false;
$charset = ( empty ( $LANGUAGE ) ? 'iso-8859-1' : translate ( 'charset' ) );
$checked = ' checked="checked"';
$error =
 ( empty ( $REPORTS_ENABLED ) || $REPORTS_ENABLED != 'Y' || $login == '__public__'
   ? print_not_auth (12) : '' );
$report_id = getValue ( 'report_id', '-?[0-9]+', true );
$selected = ' selected="selected"';
$show_participants = ( $single_user == 'Y' || $DISABLE_PARTICIPANTS_FIELD == 'Y'
  ? false : true );
$updating_public =  ( $is_admin && ! empty ( $public ) && $PUBLIC_ACCESS == 'Y' );

$report_user = ( $updating_public ? '__public__' : '');

if ( empty ( $report_id ) ) {
  $adding_report = true;
  $include_header = $report_allow_nav = 'Y';
  $report_id = -1;
  $report_is_global = 'N';
}

// Set date range options.
$ranges = array (
  '0' => translate ( 'Tomorrow' ),
  '1' => translate ( 'Today' ),
  '2' => translate ( 'Yesterday' ),
  '3' => translate ( 'Day before yesterday' ),
  '10' => translate ( 'Next week' ),
  '11' => translate ( 'This week' ),
  '12' => translate ( 'Last week' ),
  '13' => translate ( 'Week before last' ),
  '20' => translate ( 'Next week and week after' ),
  '21' => translate ( 'This week and next week' ),
  '22' => translate ( 'Last week and this week' ),
  '23' => translate ( 'Last two weeks' ),
  '30' => translate ( 'Next month' ),
  '31' => translate ( 'This month' ),
  '32' => translate ( 'Last month' ),
  '33' => translate ( 'Month before last' ),
  '40' => translate ( 'Next year' ),
  '41' => translate ( 'This year' ),
  '42' => translate ( 'Last year' ),
  '43' => translate ( 'Year before last' ),
  '50' => translate ( 'Next 14 days' ),
  '51' => translate ( 'Next 30 days' ),
  '52' => translate ( 'Next 60 days' ),
  '53' => translate ( 'Next 90 days' ),
  '54' => translate ( 'Next 180 days' ),
  '55' => translate ( 'Next 365 days' ),
  );

// Get list of users visible to the current user.
if ( empty ( $error ) && $show_participants ) {
  $userlist = get_my_users ( '', 'view' );
  if ( $NONUSER_ENABLED == 'Y' ) {
    // Restrict NUC list if groups are enabled.
    $nonusers = get_my_nonusers ( $login, true, 'view' );
    $userlist = ( $NONUSER_AT_TOP == 'Y'
      ? array_merge ( $nonusers, $userlist )
      : array_merge ( $userlist, $nonusers ) );
  }
  $userlistcnt = count ( $userlist );
}

// Default values.
$day_template = '<dt><b>${date}</b></dt>
<dd><dl>${events}</dl></dd>';

$event_template = '<dt>${name}</dt>
<dd><b>' . translate ( 'Date' ) . ':</b> ${date}<br />
<b>' . translate ( 'Time' ) . ':</b> ${time}<br />
${description}</dd>
';

$page_template = '<dl>${days}</dl>';

// Setup option arrays.
$day_options = array ( 'events', 'date', 'fulldate', 'report_id' );

$event_options = array ( 'name', 'description', 'date', 'fulldate', 'time',
  'starttime', 'endtime', 'duration', 'location', 'url', 'priority', 'href',
  'user', 'fullname', 'report_id' );

$page_options = array ( 'days', 'report_id' );

/* Generate clickable option lists.
 */
function print_options ( $textarea, $option ) {
  // Use ASCII values for ${}.
  echo '
            <a onclick="addMe( \'' . $textarea . '\', \'${' . $option
   . '}\' )">${' . $option . '}</a><br />';
}

if ( empty ( $error ) && $report_id >= 0 ) {
  $res = dbi_execute ( 'SELECT cal_login, cal_report_id, cal_is_global,
    cal_report_type, cal_include_header, cal_report_name, cal_time_range,
    cal_user, cal_allow_nav, cal_cat_id, cal_include_empty, cal_show_in_trailer,
    cal_update_date FROM webcal_report WHERE cal_report_id = ?',
    array ( $report_id ) );
  if ( $res ) {
    if ( $row = dbi_fetch_row ( $res ) ) {
      $i = 0;
      $report_login = $row[$i++];
      $report_id = $row[$i++];
      $report_is_global = $row[$i++];
      $report_type = $row[$i++];
      $report_include_header = $row[$i++];
      $report_name = $row[$i++];
      $report_time_range = $row[$i++];
      $report_user = $row[$i++];
      $report_allow_nav = $row[$i++];
      $report_cat_id = $row[$i++];
      $report_include_empty = $row[$i++];
      $report_show_in_menu = $row[$i++];
      $report_update_date = $row[$i++];

      // Check permissions.
      if ( $show_participants && ! empty ( $report_user ) ) {
        $user_is_in_list = false;
        for ( $i = 0; $i < $userlistcnt; $i++ ) {
          if ( $report_user == $userlist[$i]['cal_login'] )
            $user_is_in_list = true;
        }
        if ( ! $user_is_in_list && $report_login != $login && ! $is_admin )
          $error = print_not_auth (13);
      }
      if ( ! $is_admin && $login != $report_login )
        // Only creator or an admin can edit/delete the event.
        $error = print_not_auth (3);

      // If we are editing a public user report we need to set $updating_public.
      if ( $is_admin && $report_login == '__public__' )
        $updating_public = true;
    } else
      // translate ( 'Invalid report id.' )
      $error = str_replace ( 'XXX', $report_id,
        translate ( 'Invalid report id XXX.' ) );

    dbi_free_result ( $res );
  } else
    $error = db_error ();

  $res = dbi_execute ( 'SELECT cal_template_type, cal_template_text
    FROM webcal_report_template WHERE cal_report_id = ?', array ( $report_id ) );
  if ( $res ) {
    while ( $row = dbi_fetch_row ( $res ) ) {
      if ( $row[0] == 'D' )
        $day_template = $row[1];
      elseif ( $row[0] == 'E' )
        $event_template = $row[1];
      elseif ( $row[0] == 'P' )
        $page_template = $row[1];
    }
    dbi_free_result ( $res );
  }
} else {
  // Default values for new report.
  $report_allow_nav = $report_include_header = 'Y';
  $report_cat_id = $report_update_date = '';
  $report_id = -1;
  $report_include_empty = $report_is_global = $report_show_in_menu = 'N';
  $report_login = $login;
  $report_name = translate ( 'Unnamed Report' );
  $report_time_range = 11; // Current week.
  $report_type = 'html';
  // $report_user already set.
}

print_header ();

if ( ! empty ( $error ) ) {
  echo $error . print_trailer ( false );
  exit;
}

ob_start ();

echo '
    <h2>'
 . ( $updating_public ? translate ( $PUBLIC_ACCESS_FULLNAME ) . ' ' : '' )
 . ( $adding_report ? translate ( 'Add Report' ) : translate ( 'Edit Report' ) )
 . '</h2>
    <form action="edit_report_handler.php" method="post" name="reportform">'
 . ( $updating_public ? '
      <input type="hidden" name="public" value="1" />' : '' )
 . ( ! $adding_report ? '
      <input type="hidden" name="report_id" value="'
   . $report_id . '" />' : '' ) . '
      <table>
        <tr>
          <td><label for="rpt_name">' . translate ( 'Report name' )
 . ':</label></td>
          <td><input type="text" name="report_name" id="rpt_name" size="40" '
 . 'maxlength="50" value="' . $report_name . '" /></td>
        </tr>';

if ( $show_participants ) {
  echo '
        <tr>
          <td><label for="rpt_user">' . translate ( 'User' ) . ':</label></td>
          <td>
            <select name="report_user" id="rpt_user" size="1">
              <option value=""' . ( empty ( $report_user ) ? $selected : '' )
   . '>' . translate ( 'Current User' ) . '</option>';

  for ( $i = 0; $i < $userlistcnt; $i++ ) {
    echo '
              <option value="' . $userlist[$i]['cal_login'] . '"'
     . ( ! empty ( $report_user ) && $report_user == $userlist[$i]['cal_login']
      ? $selected : '' ) . '>' . $userlist[$i]['cal_fullname'] . '</option>';
  }

  echo '
            </select>
          </td>
        </tr>';
}

echo ( $is_admin ? '
        <tr>
          <td><label>' . translate ( 'Global' ) . ':</label></td>
          <td>' . print_radio ( 'is_global', '', '',
    ( ! empty ( $report_is_global ) && ( $report_is_global == 'Y'
        ? 'Y' : 'N' ) ) ) . '</td>
        </tr>'

  // The report will always be shown in the menu for the creator of the report.
  // For admin users who create a global report,
  // allow option of adding to all users menu.
  . '
        <tr>
          <td><label>' . translate ( 'Include link in menu' ) . ':</label></td>
          <td>' . print_radio ( 'show_in_trailer', '', '',
    ( ! empty ( $report_show_in_menu ) && ( $report_show_in_menu == 'Y'
        ? 'Y' : 'N' ) ) ) . '</td>
        </tr>' : '' ) . '
        <tr>
          <td><label>' . translate ( 'Include standard header/trailer' )
 . ':</label></td>
          <td>' . print_radio ( 'include_header', '', '',
  ( ! empty ( $report_include_header ) &&
    ( $report_include_header == 'Y' ? 'Y' : 'N' ) ) ) . '</td>
        </tr>
        <tr>
          <td><label>' . translate ( 'Include previous/next links' )
 . ':</label></td>
          <td>' . print_radio ( 'allow_nav', '', '',
  ( ! empty ( $report_allow_nav ) && ( $report_allow_nav == 'Y' ? 'Y' : 'N' ) ) )
 . '</td>
        </tr>
        <tr>
          <td><label>' . translate ( 'Include empty dates' ) . ':</label></td>
          <td>' . print_radio ( 'include_empty', '', '',
  ( ! empty ( $report_include_empty ) &&
    ( $report_include_empty == 'Y' ? 'Y' : 'N' ) ) ) . '</td>
        </tr>
        <tr>
          <td><label for="rpt_time_range">' . translate ( 'Date range' )
 . ':</label></td>
          <td>
            <select name="time_range" id="rpt_time_range">';

while ( list ( $num, $descr ) = each ( $ranges ) ) {
  echo '
              <option value="' . $num . '"'
   . ( $report_time_range == $num ? $selected : '' )
   . '>' . $descr . '</option>';
}

echo '
            </select>
          </td>
        </tr>';

if ( $CATEGORIES_ENABLED == 'Y' ) {
  echo '
        <tr>
          <td><label for="rpt_cat_id">' . translate ( 'Category' )
   . ':</label></td>
          <td>
            <select name="cat_id" id="rpt_cat_id">
              <option value="">' . translate ( 'None' ) . '</option>';

  while ( list ( $K, $V ) = each ( $categories ) ) {
    echo '
              <option value="' . $K . '"' . ( $report_cat_id == $K ? $selected : '' )
     . '>' . htmlentities ( $V['cat_name'] ) . '</option>';
  }

  echo '
            </select>
          </td>
        </tr>';
} //end $CATEGORIES_ENABLED test
echo '
      </table>
      <table>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td colspan="2"><label>' . translate ( 'Template variables' )
 . '</label></td>
        </tr>
        <tr>
          <td valign="top"><label>' . translate ( 'Page template' )
 . ':</label></td>
          <td><textarea rows="12" cols="60" name="page_template">'
 . htmlentities ( $page_template, ENT_COMPAT, $charset ) . '</textarea></td>
          <td class="aligntop cursoradd" colspan="2">';

foreach ( $page_options as $option ) {
  print_options ( 'page_template', $option );
}

echo '
          </td>
        </tr>
        <tr>
          <td valign="top"><label>' . translate ( 'Day template' )
 . ':</label></td>
          <td><textarea rows="12" cols="60" name="day_template">'
 . htmlentities ( $day_template, ENT_COMPAT, $charset ) . '</textarea></td>
          <td class="aligntop cursoradd" colspan="2">';

foreach ( $day_options as $option ) {
  print_options ( 'day_template', $option );
}

echo '
          </td>
        </tr>
        <tr>
          <td valign="top"><label>' . translate ( 'Event template' )
 . ':</label></td>
          <td><textarea rows="12" cols="60" name="event_template" id="event_template">'
 . htmlentities ( $event_template, ENT_COMPAT, $charset ) . '</textarea></td>
          <td class="aligntop cursoradd" width="150px">';

foreach ( $event_options as $option ) {
  print_options ( 'event_template', $option );
}

echo '
          </td>
          <td class="aligntop cursoradd">';

$extra_names = get_site_extras_names( EXTRA_DISPLAY_REPORT );
if ( count ( $extra_names ) > 0 )
  echo '
            <label>' . translate ( 'Site Extras' ) . '</label><br />';

foreach ( $extra_names as $name ) {
  print_options ( 'event_template', 'extra:' . $name );
}

echo '
          </td>
        </tr>
        <tr>
          <td colspan="4">
            <input type="submit" value="' . translate ( 'Save' ) . '" />'
 . ( $adding_report ? '' : '&nbsp;&nbsp;
            <input type="submit" name="delete" value="'
   . translate ( 'Delete' ) . '" onclick="return confirm( \''
   . str_replace ( 'XXX', translate ( 'report' ),
    translate ( 'Are you sure you want to delete this XXX?' ) )
   . '\');" />' );

ob_end_flush ();

?>
          </td>
        </tr>
      </table>
    </form>
    <script type="text/javascript" language="javascript">
<!-- <![CDATA[
    // This script borrowed from phpMyAdmin with some mofification.
      function addMe ( areaname, myValue ) {
        var textarea = document.reportform.elements[areaname];
        // IE support.
        if ( document.selection ) {
          textarea.focus ();
          sel = document.selection.createRange ();
          sel.text = myValue;
        }
        // MOZILLA/NETSCAPE support.
        else if ( textarea.selectionStart || textarea.selectionStart == '0' ) {
          var
            startPos = textarea.selectionStart,
            endPos = textarea.selectionEnd;

          textarea.value = textarea.value.substring ( 0, startPos ) + myValue
            + textarea.value.substring ( endPos, textarea.value.length );
        }
        else {
          textarea.value += myValue;
        }
      }
//]]> -->
    </script>
<?php echo print_trailer ();

?>

Added edit_report_handler.php.

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?php
/* $Id: edit_report_handler.php,v 1.32.2.8 2012/02/28 02:07:45 cknudsen Exp $
 *
 * Page Description:
 * This page will handle the form submission from edit_report.php
 * and either add, update or delete a report.
 *
 * Input Parameters:
 * report_id (optional) - the report id of the report to edit.
 *                        If blank, user is adding a new report.
 * public (optional) -    If set to '1' and user is an admin user,
 *                        then we are creating a report for the public user.
 * report_name
 * report_user
 * is_global (Y or N)
 * include_header (Y or N)
 * time_range
 * cat_id
 * allow_nav
 * include_empty
 * show_in_trailer
 * delete (if 'delete' button pressed)
 * page_template
 * day_template
 * event_template
 *
 * Security:
 * Same as in edit_report.php...
 * If system setting $REPORTS_ENABLED is set to anything other than 'Y',
 * then don't allow access to this page.
 * If $ALLOW_VIEW_OTHER is 'N', then do not allow selection of participants.
 * Can only delete/edit an event if you are the creator of the event
 * or you are an admin user.
 */
include_once 'includes/init.php';
require_valide_referring_url ();
load_user_categories ();

$error = ( empty ( $REPORTS_ENABLED ) || $REPORTS_ENABLED != 'Y'
  ? print_not_auth (12) : '' );
$report_id = getValue ( 'report_id', '-?[0-9]+', true );
$public = getPostValue ( 'public' );
$report_name = getPostValue ( 'report_name' );
$report_user = getPostValue ( 'report_user' );
$time_range = getPostValue ( 'time_range' );
$cat_id = getValue ( 'cat_id', '-?[0-9,\-]*', true );
$page_template = getPostValue ( 'page_template' );
$day_template = getPostValue ( 'day_template' );
$event_template = getPostValue ( 'event_template' );
$delete = getPostValue ( 'delete' );
$updating_public = ( $is_admin && ! empty ( $public ) && $PUBLIC_ACCESS == 'Y' );

if ( $single_user == 'Y' || $DISABLE_PARTICIPANTS_FIELD == 'Y' )
  $report_user = '';

if ( ! $is_admin )
  $is_global = 'N';

$adding_report = ( empty ( $report_id ) || $report_id <= 0 );

// Check permissions.
// Can only edit/delete if you created the event or you are an admin.
if ( empty ( $error ) && $single_user != 'N' && !
    empty ( $report_id ) && $report_id > 0 && ! $is_admin ) {
  $res = dbi_execute ( 'SELECT cal_login FROM webcal_report WHERE report_id = ?',
    array ( $report_id ) );
  if ( $res ) {
    if ( $row = dbi_fetch_row ( $res ) ) {
      if ( $row[0] != $login )
        $error = print_not_auth (5);
    } else
      $error = str_replace ( 'XXX', $report_id,
        translate ( 'No such report id XXX.' ) );

    dbi_free_result ( $res );
  } else
    $error = db_error ();
}

// Validate templates to make sure the required variables are found.
// Page template must include ${days}.
if ( empty ( $error ) ) {
  $errStr = '
    <p>' . translate ( 'Error' ) . ' [';
  // translate ( 'Variable N not found' )
  $noVarXXX = ']: ' . translate ( 'Variable XXX not found.' ) . '</p>';
  if ( ! strstr ( $page_template, '${days}' ) )
    $error .= $errStr . translate ( 'Page template' )
     . str_replace ( 'XXX', '${days}', $noVarXXX );

  // Day template must include ${events}.
  if ( ! strstr ( $day_template, '${events}' ) )
    $error .= $errStr . translate ( 'Day template' )
     . str_replace ( 'XXX', '${events}', $noVarXXX );

  // Event template must include ${name}.
  if ( ! strstr ( $event_template, '${name}' ) )
    $error .= $errStr . translate ( 'Event template' )
     . str_replace ( 'XXX', '${name}', $noVarXXX );
}
$delete = getPostValue ( 'delete' );
if ( empty ( $error ) && ! empty ( $report_id ) && ! empty ( $delete ) ) {
  if ( ! dbi_execute ( 'DELETE FROM webcal_report_template WHERE cal_report_id = ?',
      array ( $report_id ) ) )
    $error = db_error ();

  if ( empty ( $error ) && ! dbi_execute ( 'DELETE FROM webcal_report
    WHERE cal_report_id = ?', array ( $report_id ) ) )
    $error = db_error ();
  // Send back to main report listing page.
  if ( empty ( $error ) )
    do_redirect ( 'report.php' );
}

if ( empty ( $error ) ) {
  if ( empty ( $report_name ) || trim ( $report_name ) == '' )
    $report_name = translate ( 'Unnamed Report' );

  $names = array ( 'cal_login', 'cal_update_date', 'cal_report_type',
    'cal_report_name', 'cal_user', 'cal_include_header', 'cal_time_range',
    'cal_cat_id', 'cal_allow_nav', 'cal_include_empty', 'cal_is_global',
    'cal_show_in_trailer' );

  $values = array (
    ( $updating_public ? '__public__' : $login ),
    date ( 'Ymd' ),
    'html',
    $report_name,
    ( ! $is_admin || empty ( $report_user ) ? null : $report_user ),
    ( empty ( $include_header ) || $include_header != 'Y' ? 'N' : 'Y' ),
    ( isset ( $time_range ) ? $time_range : 11 ),
    ( empty ( $cat_id ) ? null : $cat_id ),
    ( empty ( $allow_nav ) || $allow_nav != 'Y' ? 'N' : 'Y' ),
    ( empty ( $include_empty ) || $include_empty != 'Y' ? 'N' : 'Y' ),
    ( empty ( $is_global ) || $is_global != 'Y' ? 'N' : 'Y' ),
    ( empty ( $show_in_trailer ) || $show_in_trailer != 'Y' ? 'N' : 'Y' ) );

  if ( $adding_report ) {
    $newid = 1;
    $res = dbi_execute ( 'SELECT MAX( cal_report_id ) FROM webcal_report' );
    if ( $res ) {
      if ( $row = dbi_fetch_row ( $res ) )
        $newid = $row[0] + 1;

      dbi_free_result ( $res );
    }
    $names[] = 'cal_report_id';
    $values[] = $newid;

    $sql = 'INSERT INTO webcal_report ( ';
    $sql_v = '';

    $namecnt = count ( $names );
    for ( $i = 0; $i < $namecnt; $i++ ) {
      $sql .= ( $i > 0 ? ', ' : '' ) . $names[$i];
      $sql_v .= ( $i > 0 ? ', ' : '' ) . '?';
    }
    $sql .= ' ) VALUES ( ' . $sql_v . ' )';
    $report_id = $newid;
  } else {
    $sql = 'UPDATE webcal_report SET ';
    $namecnt = count ( $names );
    for ( $i = 0; $i < $namecnt; $i++ ) {
      $sql .= ( $i > 0 ? ', ' : '' ) . "$names[$i] = ?";
    }
    $sql .= ' WHERE cal_report_id = ?';
    $values[] = $report_id; // Push the $report_id to $values.
  }
}

if ( empty ( $error ) && ! dbi_execute ( $sql, $values ) )
  $error = db_error ();

if ( empty ( $error ) ) {
  if ( ! $adding_report ) {
    if ( ! dbi_execute ( 'DELETE FROM webcal_report_template
      WHERE cal_report_id = ?', array ( $report_id ) ) )
      $error = db_error ();
  }
  $ins_sql = 'INSERT INTO webcal_report_template
    ( cal_report_id, cal_template_type, cal_template_text ) VALUES ( ?, ?, ? )';

  if ( empty ( $error ) && ! dbi_execute ( $ins_sql,
        array ( $report_id, 'D', $day_template ) ) )
    $error = db_error ();

  if ( empty ( $error ) && ! dbi_execute ( $ins_sql,
        array ( $report_id, 'E', $event_template ) ) )
    $error = db_error ();

  if ( empty ( $error ) && ! dbi_execute ( $ins_sql,
        array ( $report_id, 'P', $page_template ) ) )
    $error = db_error ();
}

if ( empty ( $error ) ) {
  do_redirect ( 'report.php' . ( $updating_public ? '?public=1' : '' ) );
  exit;
}

print_header ();
echo print_error ( $error ) . print_trailer ();

?>

Added edit_template.php.































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
/* $Id: edit_template.php,v 1.36.2.3 2012/02/28 02:07:45 cknudsen Exp $
 *
 * Page Description:
 * This page will present the HTML form to edit an entry in the cal_report table,
 * and this page will also process the form.
 * This is only used for editing the custom header/trailer.
 * The report_id is always 0.
 *
 * Input Parameters:
 * type - "header" or "trailer"
 *
 * Security:
 * Admin permissions are checked by the WebCalendar class.
 */
include_once 'includes/init.php';
require_valide_referring_url ();

$cur = $error = '';
$found = $foundOld = false;
$report_id = 0;
$type = getValue ( 'type', 'H|S|T', true );
$user = '__system__';

if ( ! empty ( $ALLOW_USER_HEADER ) && $ALLOW_USER_HEADER == 'Y' ) {
  $user = getValue ( 'user' );
  if ( empty ( $user ) )
    $user = '__system__';
}

if ( $user == '__system__' )
  assert ( '($is_admin && ! access_is_enabled () ) ||
    access_can_access_function ( ACCESS_SYSTEM_SETTINGS )' );

// Get existing value.
$res = dbi_execute ( 'SELECT cal_template_text FROM webcal_user_template
  WHERE cal_type = ? AND cal_login = ?', array ( $type, $user ) );
if ( $res ) {
  if ( $row = dbi_fetch_row ( $res ) ) {
    $cur = $row[0];
    $found = true;
  }
  dbi_free_result ( $res );
}

// Check the cal_template_text table
// since that is where we stored it in 1.0 and before.
if ( ! $found ) {
  $res = dbi_execute ( 'SELECT cal_template_text FROM webcal_report_template
    WHERE cal_template_type = ? AND cal_report_id = 0', array ( $type ) );
  if ( $res ) {
    if ( $row = dbi_fetch_row ( $res ) ) {
      $cur = $row[0];
      $foundOld = true;
    }
    dbi_free_result ( $res );
  }
}

if ( empty ( $REQUEST_METHOD ) )
  $REQUEST_METHOD = $_SERVER['REQUEST_METHOD'];

// Handle form submission.
if ( $REQUEST_METHOD == 'POST' ) {
  // Was this a delete request?
  $delete = getPostValue ( 'delete' );
  if ( $user != '__system__' && ! empty ( $delete ) ) {
    dbi_execute ( 'DELETE FROM webcal_user_template WHERE cal_type = ?
      AND cal_login = ?', array ( $type, $user ) );
    echo '<html><body onload="window.close();"></body></html>';
    exit;
  }

  $query_params = array ( getPostValue ( 'template' ), $type, $user );

  if ( $found )
    $sql = 'UPDATE webcal_user_template SET cal_template_text = ?
      WHERE cal_type = ? AND cal_login = ?';
  else {
    $sql = 'INSERT INTO webcal_user_template ( cal_template_text, cal_type,
      cal_login ) VALUES ( ?, ?, ? )';

    if ( $foundOld && $user == '__system__' )
      // User is upgrading from WebCalendar 1.0 to 1.1.
      // Delete from the webcal_report_template table and move the info
      // to the new webcal_user_template table.
      dbi_execute ( 'DELETE FROM webcal_report_template
        WHERE cal_template_type = ? AND cal_report_id = 0 ', array ( $type ) );
  }
  if ( ! dbi_execute ( $sql, $query_params ) )
    $error = db_error ();
  else {
    echo '<html>
  <head></head>
  <body onload="window.close();">
    Done
  </body>
</html>';
    exit;
  }
}

print_header ( '', '', '', true );
/*
 echo 'report_id: ' . $report_id . '<br />
report_name: ' . $report_name . '<br />
report_user: ' . $report_user . '<br />
';
*/
echo '
    <h2>';
if ( $type == 'H' )
  etranslate ( 'Edit Custom Header' );
elseif ( $type == 'S' )
  etranslate ( 'Edit Custom Script/Stylesheet' );
else
  etranslate ( 'Edit Custom Trailer' );

if ( $user != '__system__' ) {
  user_load_variables ( $user, 'temp_' );
  echo ' [' . $temp_fullname . ']';
}

echo '</h2>' . ( ! empty ( $error ) ? print_error ( $error ) : '
    <form action="edit_template.php" method="post" name="reportform">
      <input type="hidden" name="type" value="' . $type . '" />'
   . ( ! empty ( $ALLOW_USER_HEADER ) && $ALLOW_USER_HEADER == 'Y' && !
    empty ( $user ) && $user != '__system__' ? '
      <input type="hidden" name="user" value="' . $user . '" />' : '' ) . '
      <textarea rows="15" cols="60" name="template">' . htmlspecialchars ( $cur )
   . '</textarea><br />
      <input type="button" value="' . translate ( 'Cancel' )
   . '" onclick="window.close();" />
      <input name="action" type="submit" value="' . translate ( 'Save' ) . '" />'
   . ( ! empty ( $user ) ? '
      <input name="delete" type="submit" value="' . translate ( 'Delete' )
     . '" onclick="return confirm( \''
     . str_replace ( 'XXX', translate ( 'entry' ),
      translate ( 'Are you sure you want to delete this XXX?' ) ) . '\');" />'
    : '' ) . '
    </form>' ) . "\n" . print_trailer ( false, true, true );

?>

Added edit_user.php.











































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?php
/* $Id: edit_user.php,v 1.65.2.6 2008/04/21 19:18:16 umcesrjones Exp $ */
include_once 'includes/init.php';

$error = '';

if ( ! $is_admin )
  $user = $login;

// cannot edit public user.
if ( $user == '__public__' )
  $user = $login;

// don't allow them to create new users if it's not allowed
if ( empty ( $user ) ) {
  // asking to create a new user
  if ( ! $is_admin ) {
    // must be admin...
    if ( ! access_can_access_function ( ACCESS_USER_MANAGEMENT ) ) {
      $error = print_not_auth (15);
    }
  }
  if ( ! $admin_can_add_user ) {
    // if adding users is not allowed...
    $error = print_not_auth (16);
  }
} else {
  // User is editing their account info
  if ( ! access_can_access_function ( ACCESS_ACCOUNT_INFO ) )
    $error = print_not_auth (17);
}

$disableCustom = true;
$INC = array ('js/edit_user.php/false');
print_header ( $INC, '', '', $disableCustom, '', true, false );

if ( ! empty ( $error ) ) {
  echo print_error ( $error );
} else {
?>
<table>
<tr><td style="vertical-align:top; width:50%;">
<h2><?php
 if ( ! empty ( $user ) ) {
  user_load_variables ( $user, 'u' );
  echo translate ( 'Edit User' );
 } else {
  echo translate ( 'Add User' );
 }
?></h2>
<form action="edit_user_handler.php" name="edituser" method="post" onsubmit="return valid_form( this );">
<input type="hidden" name="formtype" value="edituser" />
<?php
 if ( empty ( $user ) ) {
  echo '<input type="hidden" name="add" value="1" />' . "\n";
 }
?>
<table>
 <tr><td>
  <label for="username"><?php etranslate ( 'Username' )?>:</label></td><td>
  <?php
    if ( ! empty ( $user ) ) {
      if ( $is_admin )
        echo $user . '<input name="user" type="hidden" value="' .
          htmlspecialchars ( $user ) . "\" />\n";
      else
        echo $user;
    } else {
      echo '<input type="text" name="user" id="username" size="25" onchange="check_name();" maxlength="25" />' . "\n";