List.pm 369 KB
Newer Older
1
# list.pm - This module includes all list processing functions
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# RCS Identication ; $Revision$ ; $Date$ 
#
# Sympa - SYsteme de Multi-Postage Automatique
# Copyright (c) 1997, 1998, 1999, 2000, 2001 Comite Reseau des Universites
# Copyright (c) 1997,1998, 1999 Institut Pasteur & Christophe Wolfhugel
#
# 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.
root's avatar
root committed
21
22
23
24

package List;

use strict;
25
require Fetch;
26
require Exporter;
salaun's avatar
salaun committed
27
#require Encode;
28
require 'tools.pl';
29
require "--LIBDIR--/tt2.pl";
30

31
32
my @ISA = qw(Exporter);
my @EXPORT = qw(%list_of_lists);
root's avatar
root committed
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

=head1 CONSTRUCTOR

=item new( [PHRASE] )

 List->new();

Creates a new object which will be used for a list and
eventually loads the list if a name is given. Returns
a List object.

=back

=head1 METHODS

=over 4

=item load ( LIST )

Loads the indicated list into the object.

=item save ( LIST )

Saves the indicated list object to the disk files.

=item savestats ()

Saves updates the statistics file on disk.

=item update_stats( BYTES )

Updates the stats, argument is number of bytes, returns the next
sequence number. Does nothing if no stats.

=item send_sub_to_owner ( WHO, COMMENT )
Send a message to the list owners telling that someone
wanted to subscribe to the list.

=item send_to_editor ( MSG )
72
    
root's avatar
root committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
Send a Mail::Internet type object to the editor (for approval).

=item send_msg ( MSG )

Sends the Mail::Internet message to the list.

=item send_file ( FILE, USER, GECOS )

Sends the file to the USER. FILE may only be welcome for now.

=item delete_user ( ARRAY )

Delete the indicated users from the list.
 
87
88
89
90
=item delete_admin_user ( ROLE, ARRAY )

Delete the indicated admin user with the predefined role from the list.

root's avatar
root committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
=item get_cookie ()

Returns the cookie for a list, if available.

=item get_max_size ()

Returns the maximum allowed size for a message.

=item get_reply_to ()

Returns an array with the Reply-To values.

=item get_default_user_options ()

Returns a default option of the list for subscription.

=item get_total ()

Returns the number of subscribers to the list.

111
=item get_user_db ( USER )
root's avatar
root committed
112
113
114
115

Returns a hash with the informations regarding the indicated
user.

116
117
118
119
120
121
122
123
=item get_subscriber ( USER )

Returns a subscriber of the list.

=item get_admin_user ( ROLE, USER)

Return an admin user of the list with predefined role

root's avatar
root committed
124
125
126
127
=item get_first_user ()

Returns a hash to the first user on the list.

128
129
130
131
=item get_first_admin_user ( ROLE )

Returns a hash to the first admin user with predifined role on the list.

root's avatar
root committed
132
133
134
135
136
=item get_next_user ()

Returns a hash to the next users, until we reach the end of
the list.

137
138
139
140
141
=item get_next_admin_user ()

Returns a hash to the next admin users, until we reach the end of
the list.

root's avatar
root committed
142
143
144
145
=item update_user ( USER, HASHPTR )

Sets the new values given in the hash for the user.

146
147
148
149
=item update_admin_user ( USER, ROLE, HASHPTR )

Sets the new values given in the hash for the admin user.

root's avatar
root committed
150
151
152
153
154
=item add_user ( USER, HASHPTR )

Adds a new user to the list. May overwrite existing
entries.

155
156
157
158
159
=item add_admin_user ( USER, ROLE, HASHPTR )

Adds a new admin user to the list. May overwrite existing
entries.

root's avatar
root committed
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
=item is_user ( USER )

Returns true if the indicated user is member of the list.
 
=item am_i ( FUNCTION, USER )

Returns true is USER has FUNCTION (owner, editor) on the
list.

=item get_state ( FLAG )

Returns the value for a flag : sig or sub.

=item may_do ( ACTION, USER )

Chcks is USER may do the ACTION for the list. ACTION can be
one of following : send, review, index, getm add, del,
reconfirm, purge.

=item is_moderated ()

Returns true if the list is moderated.

=item archive_exist ( FILE )

Returns true if the indicated file exists.

=item archive_send ( WHO, FILE )

Send the indicated archive file to the user, if it exists.

=item archive_ls ()

Returns the list of available files, if any.

=item archive_msg ( MSG )

Archives the Mail::Internet message given as argument.

=item is_archived ()

Returns true is the list is configured to keep archives of
its messages.

=item get_stats ( OPTION )

Returns either a formatted printable strings or an array whith
the statistics. OPTION can be 'text' or 'array'.

=item print_info ( FDNAME )

Print the list informations to the given file descriptor, or the
currently selected descriptor.

=cut

use Carp;

use Mail::Header;
use Archive;
use Language;
use Log;
use Conf;
salaun's avatar
salaun committed
223
use mail;
224
use Ldap;
root's avatar
root committed
225
226
227
use Time::Local;
use MIME::Entity;
use MIME::Words;
228
use MIME::WordDecoder;
root's avatar
root committed
229
use MIME::Parser;
230
use Message;
231
use Family;
232
use PlainDigest;
root's avatar
root committed
233
234

## Database and SQL statement handlers
235
my ($dbh, $sth, $db_connected, @sth_stack, $use_db, $include_lock_count, $include_admin_user_lock_count);
236
237

my %list_cache;
salaun's avatar
salaun committed
238
my %persistent_cache;
239

root's avatar
root committed
240
241
242
243
244
my %date_format = (
		   'read' => {
		       'Pg' => 'date_part(\'epoch\',%s)',
		       'mysql' => 'UNIX_TIMESTAMP(%s)',
		       'Oracle' => '((to_number(to_char(%s,\'J\')) - to_number(to_char(to_date(\'01/01/1970\',\'dd/mm/yyyy\'), \'J\'))) * 86400) +to_number(to_char(%s,\'SSSSS\'))',
245
246
		       'Sybase' => 'datediff(second, "01/01/1970",%s)',
		       'SQLite' => 'strftime(\'%%s\',%s,\'utc\')'
root's avatar
root committed
247
248
		       },
		   'write' => {
249
		       'Pg' => '\'epoch\'::timestamp with time zone + \'%d sec\'',
root's avatar
root committed
250
251
		       'mysql' => 'FROM_UNIXTIME(%d)',
		       'Oracle' => 'to_date(to_char(round(%s/86400) + to_number(to_char(to_date(\'01/01/1970\',\'dd/mm/yyyy\'), \'J\'))) || \':\' ||to_char(mod(%s,86400)), \'J:SSSSS\')',
252
253
		       'Sybase' => 'dateadd(second,%s,"01/01/1970")',
		       'SQLite' => 'datetime(%d,\'unixepoch\',\'localtime\')'
root's avatar
root committed
254
255
256
257
258
259
260
261
		       }
	       );

## List parameters defaults
my %default = ('occurrence' => '0-1',
	       'length' => 25
	       );

262
263
my @param_order = qw (subject visibility info subscribe add unsubscribe del owner owner_include
		      send editor editor_include account topics 
264
		      host lang web_archive archive digest digest_max_size available_user_options 
265
		      default_user_options msg_topic msg_topic_keywords_apply_on msg_topic_tagging reply_to_header reply_to forced_reply_to * 
266
		      welcome_return_path remind_return_path user_data_source include_file include_remote_file 
267
		      include_list include_remote_sympa_list include_ldap_query
268
                      include_ldap_2level_query include_sql_query include_admin ttl creation update 
root's avatar
root committed
269
270
271
272
273
274
275
276
277
278
279
280
281
282
		      status serial);

## List parameters aliases
my %alias = ('reply-to' => 'reply_to',
	     'replyto' => 'reply_to',
	     'forced_replyto' => 'forced_reply_to',
	     'forced_reply-to' => 'forced_reply_to',
	     'custom-subject' => 'custom_subject',
	     'custom-header' => 'custom_header',
	     'subscription' => 'subscribe',
	     'unsubscription' => 'unsubscribe',
	     'max-size' => 'max_size');

##############################################################
salaun's avatar
salaun committed
283
## This hash COMPLETELY defines ALL list parameters     
root's avatar
root committed
284
285
286
287
288
289
290
## It is then used to load, save, view, edit list config files
##############################################################
## List parameters format accepts the following keywords :
## format :      Regexp aplied to the configuration file entry; 
##               some common regexps are defined in %regexp
## file_format : Config file format of the parameter might not be
##               the same in memory
291
## split_char:   Character used to separate multiple parameters 
root's avatar
root committed
292
293
294
295
296
297
298
## length :      Length of a scalar variable ; used in web forms
## scenario :    tells that the parameter is a scenario, providing its name
## default :     Default value for the param ; may be a configuration parameter (conf)
## synonym :     Defines synonyms for parameter values (for compatibility reasons)
## unit :        Unit of the parameter ; this is used in web forms
## occurrence :  Occurerence of the parameter in the config file
##               possible values: 0-1 | 1 | 0-n | 1-n
299
##               example : a list may have multiple owner 
salaun's avatar
salaun committed
300
## gettext_id :    Title reference in NLS catalogues
301
## description : deescription text of a parameter
salaun's avatar
salaun committed
302
## group :       Group of parameters
303
304
305
## obsolete :    Obsolete parameter ; should not be displayed 
##               nor saved
## order :       Order of parameters within paragraph
306
307
## internal :    Indicates that the parameter is an internal parameter
##               that should always be saved in the config file
308
## field_type :  used to select passwords web input type
root's avatar
root committed
309
310
311
###############################################################
%::pinfo = ('account' => {'format' => '\S+',
			  'length' => 10,
salaun's avatar
salaun committed
312
			  'gettext_id' => "Account",
salaun's avatar
salaun committed
313
			  'group' => 'other'
root's avatar
root committed
314
315
			  },
	    'add' => {'scenario' => 'add',
salaun's avatar
salaun committed
316
		      'gettext_id' => "Who can add subscribers",
salaun's avatar
salaun committed
317
		      'group' => 'command'
root's avatar
root committed
318
319
		      },
	    'anonymous_sender' => {'format' => '.+',
salaun's avatar
salaun committed
320
				   'gettext_id' => "Anonymous sender",
321
				   'group' => 'sending'
root's avatar
root committed
322
323
324
				   },
	    'archive' => {'format' => {'period' => {'format' => ['day','week','month','quarter','year'],
						    'synonym' => {'weekly' => 'week'},
salaun's avatar
salaun committed
325
						    'gettext_id' => "frequency",
326
						    'order' => 1
root's avatar
root committed
327
328
329
						},
				       'access' => {'format' => ['open','private','public','owner','closed'],
						    'synonym' => {'open' => 'public'},
salaun's avatar
salaun committed
330
						    'gettext_id' => "access right",
331
						    'order' => 2
root's avatar
root committed
332
333
						}
				   },
salaun's avatar
salaun committed
334
			  'gettext_id' => "Text archives",
salaun's avatar
salaun committed
335
			  'group' => 'archives'
root's avatar
root committed
336
		      },
337
	    'archive_crypted_msg' => {'format' => ['original','decrypted'],
338
				    'default' => 'original',
salaun's avatar
salaun committed
339
				    'gettext_id' => "Archive encrypted mails as cleartext",
340
341
				    'group' => 'archives'
				    },
342
           'available_user_options' => {'format' => {'reception' => {'format' => ['mail','notice','digest','digestplain','summary','nomail','txt','html','urlize','not_me'],
343
344
								      'occurrence' => '1-n',
								      'split_char' => ',',
345
                                      'default' => 'mail,notice,digest,digestplain,summary,nomail,txt,html,urlize,not_me',
salaun's avatar
salaun committed
346
								      'gettext_id' => "reception mode"
347
348
								      }
						  },
salaun's avatar
salaun committed
349
					 'gettext_id' => "Available subscription options",
350
					 'group' => 'sending'
351
				     },
root's avatar
root committed
352
353
354
355
356

	    'bounce' => {'format' => {'warn_rate' => {'format' => '\d+',
						      'length' => 3,
						      'unit' => '%',
						      'default' => {'conf' => 'bounce_warn_rate'},
salaun's avatar
salaun committed
357
						      'gettext_id' => "warn rate",
358
						      'order' => 1
root's avatar
root committed
359
360
361
362
363
						  },
				      'halt_rate' => {'format' => '\d+',
						      'length' => 3,
						      'unit' => '%',
						      'default' => {'conf' => 'bounce_halt_rate'},
salaun's avatar
salaun committed
364
						      'gettext_id' => "halt rate",
365
						      'order' => 2
root's avatar
root committed
366
367
						  }
				  },
salaun's avatar
salaun committed
368
			 'gettext_id' => "Bounces management",
salaun's avatar
salaun committed
369
			 'group' => 'bounces'
root's avatar
root committed
370
		     },
salaun's avatar
salaun committed
371
372
373
374
	    'bouncers_level1' => {'format' => {'rate' => {'format' => '\d+',
								 'length' => 2,
								 'unit' => 'Points',
								 'default' => {'conf' => 'default_bounce_level1_rate'},
375
								 'gettext_id' => "threshold",
salaun's avatar
salaun committed
376
377
378
379
								 'order' => 1
								 },
				               'action' => {'format' => ['remove_bouncers','notify_bouncers','none'],
								   'default' => 'notify_bouncers',
380
								   'gettext_id' => "action for this population",
salaun's avatar
salaun committed
381
382
383
384
								   'order' => 2
								   },
					       'notification' => {'format' => ['none','owner','listmaster'],
									 'default' => 'owner',
385
									 'gettext_id' => "notification",
salaun's avatar
salaun committed
386
387
388
									 'order' => 3
									 }
					   },
389
				      'gettext_id' => "Management of bouncers, 1st level",
salaun's avatar
salaun committed
390
391
392
393
394
395
				      'group' => 'bounces'
				  },
	     'bouncers_level2' => {'format' => {'rate' => {'format' => '\d+',
								 'length' => 2,
								 'unit' => 'Points',
								 'default' => {'conf' => 'default_bounce_level2_rate'},
396
								 'gettext_id' => "threshold",
salaun's avatar
salaun committed
397
398
399
400
								 'order' => 1
								 },
				               'action' => {'format' =>  ['remove_bouncers','notify_bouncers','none'],
								   'default' => 'remove_bouncers',
401
								   'gettext_id' => "action for this population",
salaun's avatar
salaun committed
402
403
404
405
								   'order' => 2
								   },
					       'notification' => {'format' => ['none','owner','listmaster'],
									 'default' => 'owner',
406
									 'gettext_id' => "notification",
salaun's avatar
salaun committed
407
408
409
									 'order' => 3
									 }
								     },
410
				      'gettext_id' => "Management of bouncers, 2nd level",
salaun's avatar
salaun committed
411
412
				      'group' => 'bounces'
				  },
root's avatar
root committed
413
414
415
416
	    'clean_delay_queuemod' => {'format' => '\d+',
				       'length' => 3,
				       'unit' => 'days',
				       'default' => {'conf' => 'clean_delay_queuemod'},
salaun's avatar
salaun committed
417
				       'gettext_id' => "Expiration of unmoderated messages",
salaun's avatar
salaun committed
418
				       'group' => 'other'
root's avatar
root committed
419
420
421
422
				       },
	    'cookie' => {'format' => '\S+',
			 'length' => 15,
			 'default' => {'conf' => 'cookie'},
salaun's avatar
salaun committed
423
			 'gettext_id' => "Secret string for generating unique keys",
salaun's avatar
salaun committed
424
			 'group' => 'other'
root's avatar
root committed
425
426
427
		     },
	    'creation' => {'format' => {'date_epoch' => {'format' => '\d+',
							 'occurrence' => '1',
salaun's avatar
salaun committed
428
							 'gettext_id' => "",
429
							 'order' => 3
root's avatar
root committed
430
431
						     },
					'date' => {'format' => '.+',
salaun's avatar
salaun committed
432
						   'gettext_id' => "",
433
						   'order' => 2
root's avatar
root committed
434
						   },
435
					'email' => {'format' => $tools::regexp{'email'},
root's avatar
root committed
436
						    'occurrence' => '1',
salaun's avatar
salaun committed
437
						    'gettext_id' => "",
438
						    'order' => 1
root's avatar
root committed
439
440
						    }
				    },
salaun's avatar
salaun committed
441
			   'gettext_id' => "Creation of the list",
442
			   'internal' => 1,
salaun's avatar
salaun committed
443
			   'group' => 'other'
root's avatar
root committed
444
445
446
447
448

		       },
	    'custom_header' => {'format' => '\S+:\s+.*',
				'length' => 30,
				'occurrence' => '0-n',
salaun's avatar
salaun committed
449
				'gettext_id' => "Custom header field",
450
				'group' => 'sending'
root's avatar
root committed
451
				},
452
	    'custom_subject' => {'format' => '.+',
root's avatar
root committed
453
				 'length' => 15,
salaun's avatar
salaun committed
454
				 'gettext_id' => "Subject tagging",
455
				 'group' => 'sending'
root's avatar
root committed
456
				 },
457
        'default_user_options' => {'format' => {'reception' => {'format' => ['digest','digestplain','mail','nomail','summary','notice','txt','html','urlize','not_me'],
root's avatar
root committed
458
								    'default' => 'mail',
salaun's avatar
salaun committed
459
								    'gettext_id' => "reception mode",
460
								    'order' => 1
root's avatar
root committed
461
462
463
								    },
						    'visibility' => {'format' => ['conceal','noconceal'],
								     'default' => 'noconceal',
salaun's avatar
salaun committed
464
								     'gettext_id' => "visibility",
465
								     'order' => 2
root's avatar
root committed
466
467
								     }
						},
salaun's avatar
salaun committed
468
				       'gettext_id' => "Subscription profile",
469
				       'group' => 'sending'
root's avatar
root committed
470
471
				   },
	    'del' => {'scenario' => 'del',
salaun's avatar
salaun committed
472
		      'gettext_id' => "Who can delete subscribers",
salaun's avatar
salaun committed
473
		      'group' => 'command'
root's avatar
root committed
474
475
		      },
	    'digest' => {'file_format' => '\d+(\s*,\s*\d+)*\s+\d+:\d+',
476
			 'format' => {'days' => {'format' => [0..6],
salaun's avatar
salaun committed
477
						 'file_format' => '1|2|3|4|5|6|7',
root's avatar
root committed
478
						 'occurrence' => '1-n',
salaun's avatar
salaun committed
479
						 'gettext_id' => "days",
480
						 'order' => 1
root's avatar
root committed
481
482
483
484
						 },
				      'hour' => {'format' => '\d+',
						 'length' => 2,
						 'occurrence' => '1',
salaun's avatar
salaun committed
485
						 'gettext_id' => "hour",
486
						 'order' => 2
root's avatar
root committed
487
488
489
490
						 },
				      'minute' => {'format' => '\d+',
						   'length' => 2,
						   'occurrence' => '1',
salaun's avatar
salaun committed
491
						   'gettext_id' => "minute",
492
						   'order' => 3
root's avatar
root committed
493
494
						   }
				  },
salaun's avatar
salaun committed
495
			 'gettext_id' => "Digest frequency",
496
			 'group' => 'sending'
root's avatar
root committed
497
		     },
salaun's avatar
salaun committed
498

499
500
501
502
503
504
505
	    'digest_max_size' => {'format' => '\d+',
				  'length' => 2,
				  'unit' => 'messages',
				  'default' => 25,
				  'gettext_id' => "Digest maximum number of messages",
				  'group' => 'sending'
		       },	    
506
	    'editor' => {'format' => {'email' => {'format' => $tools::regexp{'email'},
root's avatar
root committed
507
508
						  'length' => 30,
						  'occurrence' => '1',
salaun's avatar
salaun committed
509
						  'gettext_id' => "email address",
510
						  'order' => 1
root's avatar
root committed
511
512
513
						  },
				      'reception' => {'format' => ['mail','nomail'],
						      'default' => 'mail',
salaun's avatar
salaun committed
514
						      'gettext_id' => "reception mode",
515
						      'order' => 4
root's avatar
root committed
516
517
518
						      },
				      'gecos' => {'format' => '.+',
						  'length' => 30,
salaun's avatar
salaun committed
519
						  'gettext_id' => "name",
520
						  'order' => 2
root's avatar
root committed
521
522
523
						  },
				      'info' => {'format' => '.+',
						 'length' => 30,
salaun's avatar
salaun committed
524
						 'gettext_id' => "private information",
525
						 'order' => 3
root's avatar
root committed
526
527
528
						 }
				  },
			 'occurrence' => '0-n',
salaun's avatar
salaun committed
529
			 'gettext_id' => "Moderators",
salaun's avatar
salaun committed
530
			 'group' => 'description'
root's avatar
root committed
531
			 },
532
533
534
	    'editor_include' => {'format' => {'source' => {'datasource' => 1,
							   'occurrence' => '1',
							   'gettext_id' => 'the datasource',
535
							   'order' => 1
536
							   },
537
538
539
540
					      'source_parameters' => {'format' => '.*',
								      'occurrence' => '0-1',
								      'gettext_id' => 'datasource parameters',
								      'order' => 2
541
    								      },
542
543
544
					      'reception' => {'format' => ['mail','nomail'],
							      'default' => 'mail',
							      'gettext_id' => 'reception mode',
545
546
547
							       'order' => 3
							      }
					      
548
549
550
551
552
					      },
				  'occurrence' => '0-n',
				  'gettext_id' => 'Moderators defined in an external datasource',
				  'group' => 'description',
			      },
553
	    'expire_task' => {'task' => 'expire',
sympa-authors's avatar
sympa-authors committed
554
			      'gettext_id' => "Periodical subscription expiration task",
555
			      'group' => 'other'
556
			 },
557
558
559
560
561
562
 	    'family_name' => {'format' => $tools::regexp{'family_name'},
 			      'occurrence' => '0-1',
 			      'gettext_id' => 'Family name',
			      'internal' => 1,
 			      'group' => 'description'
 			      },
root's avatar
root committed
563
564
	    'footer_type' => {'format' => ['mime','append'],
			      'default' => 'mime',
salaun's avatar
salaun committed
565
			      'gettext_id' => "Attachment type",
566
			      'group' => 'sending'
root's avatar
root committed
567
568
			      },
	    'forced_reply_to' => {'format' => '\S+',
salaun's avatar
salaun committed
569
				  'gettext_id' => "Forced reply address",
570
				  'obsolete' => 1
root's avatar
root committed
571
			 },
572
	    'host' => {'format' => $tools::regexp{'host'},
root's avatar
root committed
573
		       'length' => 20,
salaun's avatar
salaun committed
574
		       'gettext_id' => "Internet domain",
salaun's avatar
salaun committed
575
		       'group' => 'description'
root's avatar
root committed
576
577
578
579
		   },
	    'include_file' => {'format' => '\S+',
			       'length' => 20,
			       'occurrence' => '0-n',
salaun's avatar
salaun committed
580
			       'gettext_id' => "File inclusion",
salaun's avatar
salaun committed
581
			       'group' => 'data_source'
root's avatar
root committed
582
			       },
583
584
585
586
587
588
589
590
591
592
593
594
595
	    'include_remote_file' => {'format' => {'url' => {'format' => '.+',
							     'gettext_id' => "data location URL",
							     'occurrence' => '1',
							     'length' => 50,
							     'order' => 2
							     },					       
						   'user' => {'format' => '.+',
							      'gettext_id' => "remote user",
							      'order' => 3,
							      'occurrence' => '0-1'
							      },
						   'passwd' => {'format' => '.+',
								'length' => 10,
596
								'field_type' => 'password',
597
598
599
600
601
602
603
604
605
606
607
608
609
610
								'gettext_id' => "remote password",
								'order' => 4,
								'occurrence' => '0-1'
								},							      
						    'name' => {'format' => '.+',
							       'gettext_id' => "short name for this source",
							       'length' => 15,
							       'order' => 1
							       }
						     },
				      'gettext_id' => "Remote file inclusion",
				      'occurrence' => '0-n',
				      'group' => 'data_source'
				      },				  
611
	    'include_ldap_query' => {'format' => {'host' => {'format' => $tools::regexp{'multiple_host_with_port'},
root's avatar
root committed
612
							     'occurrence' => '1',
salaun's avatar
salaun committed
613
							     'gettext_id' => "remote host",
614
							     'order' => 2
root's avatar
root committed
615
616
617
618
							     },
						  'port' => {'format' => '\d+',
							     'default' => 389,
							     'length' => 4,
salaun's avatar
salaun committed
619
							     'gettext_id' => "remote port",
620
							     'obsolete' => 1,
621
							     'order' => 2
root's avatar
root committed
622
							     },
623
						  'user' => {'format' => '.+',
salaun's avatar
salaun committed
624
							     'gettext_id' => "remote user",
625
							     'order' => 3
root's avatar
root committed
626
							     },
627
						  'passwd' => {'format' => '.+',
root's avatar
root committed
628
							       'length' => 10,
629
							       'field_type' => 'password',
salaun's avatar
salaun committed
630
							       'gettext_id' => "remote password",
631
							       'order' => 3
root's avatar
root committed
632
							       },
633
						  'suffix' => {'format' => '.+',
salaun's avatar
salaun committed
634
							       'gettext_id' => "suffix",
635
							       'order' => 4
root's avatar
root committed
636
							       },
637
						  'filter' => {'format' => '.+',
root's avatar
root committed
638
639
							       'length' => 50,
							       'occurrence' => '1',
salaun's avatar
salaun committed
640
							       'gettext_id' => "filter",
641
							       'order' => 7
root's avatar
root committed
642
643
644
645
							       },
						  'attrs' => {'format' => '\w+',
							      'length' => 15,
							      'default' => 'mail',
salaun's avatar
salaun committed
646
							      'gettext_id' => "extracted attribute",
647
							      'order' => 8
root's avatar
root committed
648
649
650
							      },
						  'select' => {'format' => ['all','first'],
							       'default' => 'first',
salaun's avatar
salaun committed
651
							       'gettext_id' => "selection (if multiple)",
652
653
654
655
							       'order' => 9
							       },
					          'scope' => {'format' => ['base','one','sub'],
							      'default' => 'sub',
salaun's avatar
salaun committed
656
							      'gettext_id' => "search scope",
657
658
659
660
661
							      'order' => 5
							      },
						  'timeout' => {'format' => '\w+',
								'default' => 30,
								'unit' => 'seconds',
salaun's avatar
salaun committed
662
								'gettext_id' => "connection timeout",
663
								'order' => 6
664
665
								},
						   'name' => {'format' => '.+',
salaun's avatar
salaun committed
666
							      'gettext_id' => "short name for this source",
667
668
669
							      'length' => 15,
							      'order' => 1
							      }
root's avatar
root committed
670
671
					      },
				     'occurrence' => '0-n',
salaun's avatar
salaun committed
672
				     'gettext_id' => "LDAP query inclusion",
salaun's avatar
salaun committed
673
				     'group' => 'data_source'
root's avatar
root committed
674
				     },
675
	    'include_ldap_2level_query' => {'format' => {'host' => {'format' => $tools::regexp{'multiple_host_with_port'},
676
							     'occurrence' => '1',
salaun's avatar
salaun committed
677
							     'gettext_id' => "remote host",
678
679
680
681
682
							     'order' => 1
							     },
						  'port' => {'format' => '\d+',
							     'default' => 389,
							     'length' => 4,
salaun's avatar
salaun committed
683
							     'gettext_id' => "remote port",
684
							     'obsolete' => 1,
685
686
							     'order' => 2
							     },
687
						  'user' => {'format' => '.+',
salaun's avatar
salaun committed
688
							     'gettext_id' => "remote user",
689
690
							     'order' => 3
							     },
691
						  'passwd' => {'format' => '.+',
692
							       'length' => 10,
693
							       'field_type' => 'password',
salaun's avatar
salaun committed
694
							       'gettext_id' => "remote password",
695
696
							       'order' => 3
							       },
697
						  'suffix1' => {'format' => '.+',
salaun's avatar
salaun committed
698
							       'gettext_id' => "first-level suffix",
699
700
							       'order' => 4
							       },
701
						  'filter1' => {'format' => '.+',
702
703
							       'length' => 50,
							       'occurrence' => '1',
salaun's avatar
salaun committed
704
							       'gettext_id' => "first-level filter",
705
706
707
708
							       'order' => 7
							       },
						  'attrs1' => {'format' => '\w+',
							      'length' => 15,
salaun's avatar
salaun committed
709
							      'gettext_id' => "first-level extracted attribute",
710
711
712
713
							      'order' => 8
							      },
						  'select1' => {'format' => ['all','first','regex'],
							       'default' => 'first',
salaun's avatar
salaun committed
714
							       'gettext_id' => "first-level selection",
715
716
717
718
							       'order' => 9
							       },
					          'scope1' => {'format' => ['base','one','sub'],
							      'default' => 'sub',
salaun's avatar
salaun committed
719
							      'gettext_id' => "first-level search scope",
720
721
722
723
724
							      'order' => 5
							      },
						  'timeout1' => {'format' => '\w+',
								'default' => 30,
								'unit' => 'seconds',
salaun's avatar
salaun committed
725
								'gettext_id' => "first-level connection timeout",
726
727
728
729
730
								'order' => 6
								},
						  'regex1' => {'format' => '.+',
								'length' => 50,
								'default' => '',
salaun's avatar
salaun committed
731
								'gettext_id' => "first-level regular expression",
732
733
								'order' => 10
								},
734
						  'suffix2' => {'format' => '.+',
salaun's avatar
salaun committed
735
							       'gettext_id' => "second-level suffix template",
736
737
							       'order' => 11
							       },
738
						  'filter2' => {'format' => '.+',
739
740
							       'length' => 50,
							       'occurrence' => '1',
salaun's avatar
salaun committed
741
							       'gettext_id' => "second-level filter template",
742
743
744
745
746
							       'order' => 14
							       },
						  'attrs2' => {'format' => '\w+',
							      'length' => 15,
							      'default' => 'mail',
salaun's avatar
salaun committed
747
							      'gettext_id' => "second-level extracted attribute",
748
749
750
751
							      'order' => 15
							      },
						  'select2' => {'format' => ['all','first','regex'],
							       'default' => 'first',
salaun's avatar
salaun committed
752
							       'gettext_id' => "second-level selection",
753
754
755
756
							       'order' => 16
							       },
					          'scope2' => {'format' => ['base','one','sub'],
							      'default' => 'sub',
salaun's avatar
salaun committed
757
							      'gettext_id' => "second-level search scope",
758
759
760
761
762
							      'order' => 12
							      },
						  'timeout2' => {'format' => '\w+',
								'default' => 30,
								'unit' => 'seconds',
salaun's avatar
salaun committed
763
								'gettext_id' => "second-level connection timeout",
764
765
766
767
768
								'order' => 13
								},
						  'regex2' => {'format' => '.+',
								'length' => 50,
								'default' => '',
salaun's avatar
salaun committed
769
								'gettext_id' => "second-level regular expression",
770
								'order' => 17
771
772
								},
						   'name' => {'format' => '.+',
salaun's avatar
salaun committed
773
							      'gettext_id' => "short name for this source",
774
775
776
777
							      'length' => 15,
							      'order' => 1
							      }

778
779
					      },
				     'occurrence' => '0-n',
salaun's avatar
salaun committed
780
				     'gettext_id' => "LDAP 2-level query inclusion",
781
782
				     'group' => 'data_source'
				     },
783
	    'include_list' => {'format' => $tools::regexp{'listname'},
root's avatar
root committed
784
			       'occurrence' => '0-n',
salaun's avatar
salaun committed
785
			       'gettext_id' => "List inclusion",
salaun's avatar
salaun committed
786
			       'group' => 'data_source'
root's avatar
root committed
787
			       },
788
	    'include_remote_sympa_list' => {'format' => {'host' => {'format' => $tools::regexp{'host'},
789
							    'occurrence' => '1',
salaun's avatar
salaun committed
790
							    'gettext_id' => "remote host",
791
792
793
794
795
							    'order' => 1
							    },
							 'port' => {'format' => '\d+',
							     'default' => 443,
							     'length' => 4,
salaun's avatar
salaun committed
796
							     'gettext_id' => "remote port",
797
798
799
800
801
							     'order' => 2
							     },
							 'path' => {'format' => '\S+',
			                                     'length' => 20,
			                                     'occurrence' => '1',
salaun's avatar
salaun committed
802
			                                     'gettext_id' => "remote path of sympa list dump",
803
804
805
806
							     'order' => 3 

			                                     },
                                                         'cert' => {'format' => ['robot','list'],
salaun's avatar
salaun committed
807
							           'gettext_id' => "certificate for authentication by remote Sympa",
808
								   'default' => 'list',
809
810
811
								    'order' => 4
								    },
							   'name' => {'format' => '.+',
salaun's avatar
salaun committed
812
								      'gettext_id' => "short name for this source",
813
814
815
816
								      'length' => 15,
								      'order' => 1
								      }
					},
817
818

			       'occurrence' => '0-n',
salaun's avatar
salaun committed
819
			       'gettext_id' => "remote list inclusion",
820
821
			       'group' => 'data_source'
			       },
822
	    'include_sql_query' => {'format' => {'db_type' => {'format' => '\S+',
root's avatar
root committed
823
							       'occurrence' => '1',
salaun's avatar
salaun committed
824
							       'gettext_id' => "database type",
825
							       'order' => 1
root's avatar
root committed
826
							       },
827
						 'host' => {'format' => $tools::regexp{'host'},
root's avatar
root committed
828
							    'occurrence' => '1',
salaun's avatar
salaun committed
829
							    'gettext_id' => "remote host",
830
							    'order' => 2
root's avatar
root committed
831
							    },
832
						 'db_name' => {'format' => '\S+',
root's avatar
root committed
833
							       'occurrence' => '1',
salaun's avatar
salaun committed
834
							       'gettext_id' => "database name",
835
							       'order' => 3 
root's avatar
root committed
836
							       },
837
						 'connect_options' => {'format' => '.+',
salaun's avatar
salaun committed
838
								       'gettext_id' => "connection options",
839
840
								       'order' => 4
								       },
841
						 'db_env' => {'format' => '\w+\=\S+(;\w+\=\S+)*',
842
							      'order' => 5,
salaun's avatar
salaun committed
843
							      'gettext_id' => "environment variables for database connexion"
844
							      },
845
						 'user' => {'format' => '\S+',
root's avatar
root committed
846
							    'occurrence' => '1',
salaun's avatar
salaun committed
847
							    'gettext_id' => "remote user",
848
							    'order' => 6
root's avatar
root committed
849
850
							    },
						 'passwd' => {'format' => '.+',
851
							      'field_type' => 'password',
salaun's avatar
salaun committed
852
							      'gettext_id' => "remote password",
853
							      'order' => 7
root's avatar
root committed
854
							      },
855
						 'sql_query' => {'format' => $tools::regexp{'sql_query'},
root's avatar
root committed
856
857
								 'length' => 50,
								 'occurrence' => '1',
salaun's avatar
salaun committed
858
								 'gettext_id' => "SQL query",
859
								 'order' => 8
root's avatar
root committed
860
								 },
861
						  'f_dir' => {'format' => '.+',
sympa-authors's avatar
sympa-authors committed
862
							     'gettext_id' => "Directory where the database is stored (used for DBD::CSV only)",
863
							     'order' => 9
864
865
							     },
						  'name' => {'format' => '.+',
salaun's avatar
salaun committed
866
							     'gettext_id' => "short name for this source",
867
868
							     'length' => 15,
							     'order' => 1
root's avatar
root committed
869
							     }
870
						 
root's avatar
root committed
871
872
					     },
				    'occurrence' => '0-n',
salaun's avatar
salaun committed
873
				    'gettext_id' => "SQL query inclusion",
salaun's avatar
salaun committed
874
				    'group' => 'data_source'
root's avatar
root committed
875
876
				    },
	    'info' => {'scenario' => 'info',
salaun's avatar
salaun committed
877
		       'gettext_id' => "Who can view list information",
salaun's avatar
salaun committed
878
		       'group' => 'command'
root's avatar
root committed
879
880
		       },
	    'invite' => {'scenario' => 'invite',
salaun's avatar
salaun committed
881
			 'gettext_id' => "Who can invite people",
salaun's avatar
salaun committed
882
			 'group' => 'command'
root's avatar
root committed
883
			 },
884
	    'lang' => {'format' => [], ## &Language::GetSupportedLanguages() called later
885
		       'file_format' => '\w+',
root's avatar
root committed
886
		       'default' => {'conf' => 'lang'},
salaun's avatar
salaun committed
887
		       'gettext_id' => "Language of the list",
salaun's avatar
salaun committed
888
		       'group' => 'description'
root's avatar
root committed
889
		   },
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
 	    'latest_instantiation' => {'format' => {'date_epoch' => {'format' => '\d+',
 								     'occurrence' => '1',
 								     'gettext_id' => 'epoch date',
 								     'order' => 3
 								     },
 						    'date' => {'format' => '.+',
 							       'gettext_id' => 'date',
 							       'order' => 2
 							       },
 						    'email' => {'format' => $tools::regexp{'email'},
 								'occurrence' => '0-1',
 								'gettext_id' => 'who ran the instantiation',
 								'order' => 1
 								}
 						},
 				       'gettext_id' => 'Latest family instantiation',
				       'internal' => 1,
				       'group' => 'other'
 				       },
root's avatar
root committed
909
910
911
912
	    'max_size' => {'format' => '\d+',
			   'length' => 8,
			   'unit' => 'bytes',
			   'default' => {'conf' => 'max_size'},
salaun's avatar
salaun committed
913
			   'gettext_id' => "Maximum message size",
914
			   'group' => 'sending'
root's avatar
root committed
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
	    'msg_topic' => {'format' => {'name' => {'format' => '\w+',
						    'length' => 15,
						    'occurrence' => '1',
						    'gettext_id' => "Message topic name",
						    'order' => 1		
						    }, 
  					 'keywords' => {'format' => '[^,\n]+(,[^,\n]+)*',
							'occurrence' => '0-1',
							'gettext_id' => "Message topic keywords",
							'order' => 2		
							},
				         'title' => {'format' => '.+',
						     'length' => 35,
						     'occurrence' => '1',
						     'gettext_id' => "Message topic title",
						     'order' => 3		
						     }
				         },
			    'occurrence' => '0-n',
			    'gettext_id' => "Topics for message categorisation",
			    'group' => 'sending'
			    },
	    'msg_topic_keywords_apply_on' => { 'format' => ['subject','body','subject_and_body'],
					       'occurrence' => '0-1',
					       'default' => 'subject',
					       'gettext_id' => "On which part of message check for message topic keywords",
					       'group' => 'sending'
					     },    

	    'msg_topic_tagging' => { 'format' => ['required','optional'],
				      'occurrence' => '0-1',
				      'default' => 'optional',
				      'gettext_id' => "Message tagging",
				      'group' => 'sending'
				      },    
						   
952
	    'owner' => {'format' => {'email' => {'format' => $tools::regexp{'email'},
root's avatar
root committed
953
954
						 'length' =>30,
						 'occurrence' => '1',
salaun's avatar
salaun committed
955
						 'gettext_id' => "email address",
956
						 'order' => 1
root's avatar
root committed
957
958
959
						 },
				     'reception' => {'format' => ['mail','nomail'],
						     'default' => 'mail',
salaun's avatar
salaun committed
960
						     'gettext_id' => "reception mode",
961
						     'order' =>5
root's avatar
root committed
962
963
964
						     },
				     'gecos' => {'format' => '.+',
						 'length' => 30,
salaun's avatar
salaun committed
965
						 'gettext_id' => "name",
966
						 'order' => 2
root's avatar
root committed
967
968
969
						 },
				     'info' => {'format' => '.+',
						'length' => 30,
salaun's avatar
salaun committed
970
						'gettext_id' => "private informations",
971
						'order' => 3
root's avatar
root committed
972
973
974
						},
				     'profile' => {'format' => ['privileged','normal'],
						   'default' => 'normal',
salaun's avatar
salaun committed
975
						   'gettext_id' => "profile",
976
						   'order' => 4
root's avatar
root committed
977
978
						   }
				 },
979
			'occurrence' => '0-n',
salaun's avatar
salaun committed
980
			'gettext_id' => "Owner",
salaun's avatar
salaun committed
981
			'group' => 'description'
root's avatar
root committed
982
			},
983
984
985
	    'owner_include' => {'format' => {'source' => {'datasource' => 1,
							  'occurrence' => '1',
							  'gettext_id' => 'the datasource',
986
987
988
989
990
991
							  'order' => 1
							  },
					     'source_parameters' => {'format' => '.*',
								     'occurrence' => '0-1',
								     'gettext_id' => 'datasource parameters',
								     'order' => 2
992
993
994
995
						      },
					     'reception' => {'format' => ['mail','nomail'],
							     'default' => 'mail',
							     'gettext_id' => 'reception mode',
996
							     'order' => 4
997
998
999
1000
							 },
					     'profile' => {'format' => ['privileged','normal'],
							   'default' => 'normal',
							   'gettext_id' => 'profile',
1001
							    'order' => 3
1002
1003
1004
1005
1006
1007
						       }
					 },
				'occurrence' => '0-n',
				'gettext_id' => 'Owners defined in an external datasource',
				'group' => 'description',
			    },
root's avatar
root committed
1008
1009
1010
	    'priority' => {'format' => [0..9,'z'],
			   'length' => 1,
			   'default' => {'conf' => 'default_list_priority'},
salaun's avatar
salaun committed
1011
			   'gettext_id' => "Priority",
1012
			   'group' => 'description'
root's avatar
root committed
1013
1014
		       },
	    'remind' => {'scenario' => 'remind',
1015
			 'gettext_id' => "Who can start a remind process",
salaun's avatar
salaun committed
1016
			 'group' => 'command'
root's avatar
root committed
1017
1018
1019
			  },
	    'remind_return_path' => {'format' => ['unique','owner'],
				     'default' => {'conf' => 'remind_return_path'},
1020
				     'gettext_id' => "Return-path of the REMIND command",
salaun's avatar
salaun committed
1021
				     'group' => 'bounces'
root's avatar
root committed
1022
				 },
1023
	    'remind_task' => {'task' => 'remind',
sympa-authors's avatar
sympa-authors committed
1024
			      'gettext-id' => 'Periodical subscription reminder task',
1025
			      'default' => {'conf' => 'default_remind_task'},
1026
			      'group' => 'other'
1027
			      },
root's avatar
root committed
1028
1029
	    'reply_to' => {'format' => '\S+',
			   'default' => 'sender',
salaun's avatar
salaun committed
1030
			   'gettext_id' => "Reply address",
1031
			   'group' => 'sending',
1032
			   'obsolete' => 1
root's avatar
root committed
1033
			   },
1034
	    'reply_to_header' => {'format' => {'value' => {'format' => ['sender','list','all','other_email'],
1035
							   'default' => 'sender',
salaun's avatar
salaun committed
1036
							   'gettext_id' => "value",
aumont's avatar
aumont committed
1037
							   'occurrence' => '1',
1038
							   'order' => 1
1039
							   },
1040
					       'other_email' => {'format' => $tools::regexp{'email'},
salaun's avatar
salaun committed
1041
								 'gettext_id' => "other email address",
1042
								 'order' => 2
1043
1044
1045
								 },
					       'apply' => {'format' => ['forced','respect'],
							   'default' => 'respect',
salaun's avatar
salaun committed
1046
							   'gettext_id' => "respect of existing header field",
1047
							   'order' => 3
1048
1049
							   }
					   },
salaun's avatar
salaun committed
1050
				  'gettext_id' => "Reply address",
1051
				  'group' => 'sending'
1052
				  },		
root's avatar
root committed
1053
	    'review' => {'scenario' => 'review',
salaun's avatar
salaun committed
1054
			 'synonym' => {'open' => 'public'},
salaun's avatar
salaun committed
1055
			 'gettext_id' => "Who can review subscribers",
salaun's avatar
salaun committed
1056
			 'group' => 'command'
root's avatar
root committed
1057
			 },
1058
1059
1060
1061
	    'rfc2369_header_fields' => {'format' => ['help','subscribe','unsubscribe','post','owner','archive'],
					'default' => {'conf' => 'rfc2369_header_fields'},
					'occurrence' => '0-n',
					'split_char' => ',',
1062
					'gettext_id' => "RFC 2369 Header fields",
1063
1064
					'group' => 'sending'
					},
root's avatar
root committed
1065
	    'send' => {'scenario' => 'send',
salaun's avatar
salaun committed
1066
		       'gettext_id' => "Who can send messages",
1067
		       'group' => 'sending'
root's avatar
root committed
1068
1069
1070
1071
		       },
	    'serial' => {'format' => '\d+',
			 'default' => 0,
			 'length' => 3,
salaun's avatar
salaun committed
1072
			 'default' => 0,
salaun's avatar
salaun committed
1073
			 'gettext_id' => "Serial number of the config",
1074
			 'internal' => 1,
salaun's avatar
salaun committed
1075
			 'group' => 'other'
root's avatar
root committed
1076
1077
			 },
	    'shared_doc' => {'format' => {'d_read' => {'scenario' => 'd_read',
salaun's avatar
salaun committed
1078
						       'gettext_id' => "Who can view",
1079
						       'order' => 1
root's avatar
root committed
1080
1081
						       },
					  'd_edit' => {'scenario' => 'd_edit',
salaun's avatar
salaun committed
1082
						       'gettext_id' =>