/[drupal]/contributions/modules/mailman_manager/mailman_manager.module
ViewVC logotype

Contents of /contributions/modules/mailman_manager/mailman_manager.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.33 - (show annotations) (download) (as text)
Sun Dec 21 05:51:01 2008 UTC (11 months ago) by taniwha
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--2
Changes since 1.32: +263 -329 lines
File MIME type: text/x-php
merged DRUPAL-6--1 into HEAD
1 <?php
2 // $Id: mailman_manager.module,v 1.32.2.1.2.13 2008/12/21 05:47:49 taniwha Exp $
3 /**
4 * @file
5 * Allows users to subscribe to Mailman mailing lists via a form in
6 * their user profile. List of mailing lists is defined by administrator.
7 * Module maintains a list of user subscriptions and passwords.
8 * Module sends requests for subscription changes to Mailman request address.
9 */
10
11 /**
12 * Implementation of hook_help().
13 */
14 function mailman_manager_help($path, $arg) {
15 switch ($path) {
16 case 'admin/modules#description':
17 return t('Utilities related to Mailman manager, subscription system and database for Mailman mailing lists.');
18 break;
19 case 'admin/help#mailman_manager':
20
21 $output = '<p>'. t('Utilities related to Mailman manager, subscription system and database for Mailman mailing lists.') .'</p>';
22 $output .= '<p>'. t("This tool works using the mailman email interface. All commands sent by this module are also BCC'ed to the list admin. One can optionally specify the web interface and/or the web archive of each list. The module can not know if a user is previously subscribed but allows the user to specify a password which can then be used to hook into an existing account.") .'</p>';
23
24 return $output;
25 break;
26 }
27 }
28
29 /**
30 * Implementation of hook_link().
31 */
32 function mailman_manager_link($type, $node = NULL, $teaser = FALSE) {
33 $links = array();
34
35 if ($type == 'page' && user_access('access content')) {
36 // $links[] = l(t('mailing %list', array('%list' => format_plural(_mailman_manager_get_count(), 'list', 'lists'))), 'mailman_manager', array('title' => t('Subscribe to mailing %list', array('%list' => format_plural(_mailman_manager_get_count(), 'list', 'lists')))));
37 $links[] = l(t('Mailing Lists'), 'mailman_manager', array('title' => t('Subscribe to mailing lists')));
38 }
39
40 return $links;
41 }
42
43 /**
44 * Implementation of hook_perm().
45 */
46 function mailman_manager_perm() {
47 return array('access mailman_manager', 'administer mailman_manager');
48 }
49
50 /**
51 * Implementation of hook_menu().
52 */
53 function mailman_manager_menu() {
54 $items = array();
55 $items['mailman_manager'] = array('title' => 'Mailing Lists',
56 'page callback' => 'mailman_manager_page',
57 'access arguments' => array('access mailman_manager'),
58 'type' => MENU_NORMAL_ITEM);
59
60 $items['admin/settings/mailman_manager'] = array('title' => 'Mailing Lists',
61 'access arguments' => array('administer mailman_manager'),
62 'description' => 'Allow users to subscribe and change their subscriptions to Mailman mailing lists.',
63 'page callback' => '_mailman_manager_admin_display',
64 'type' => MENU_NORMAL_ITEM);
65
66 $items['admin/settings/mailman_manager/add'] = array('title' => 'Add New',
67 'access arguments' => array('administer mailman_manager'),
68 'description' => 'Add new Mailman mailing lists.',
69 'page callback' => 'drupal_get_form',
70 'page arguments' => array('mailman_manager_admin_form', NULL),
71 'type' => MENU_NORMAL_ITEM);
72 $items['admin/settings/mailman_manager/edit/%'] = array('title' => 'Edit Mailing list',
73 'access arguments' => array('administer mailman_manager'),
74 'description' => 'Edit Mailman mailing lists.',
75 'page callback' => 'drupal_get_form',
76 'page arguments' => array('mailman_manager_admin_form', 4),
77 'type' => MENU__CALLBACK);
78 $items['admin/settings/mailman_manager/delete/%'] = array('title' => 'Delete Mailing list',
79 'access arguments' => array('administer mailman_manager'),
80 'description' => 'Add new Mailman mailing lists.',
81 'page callback' => 'drupal_get_form',
82 'page arguments' => array('mailman_manager_admin_delete_form', 4),
83 'type' => MENU_CALLBACK);
84
85 $items['user/%user/mailman_manager'] = array(
86 'title' => 'Mailing Lists',
87 'page callback' => 'drupal_get_form',
88 'page arguments' => array('_mailman_manager_user_form',1),
89 'type' => MENU_LOCAL_TASK,
90 'access arguments' => array('access mailman_manager'),
91 'weight' => 9,
92 );
93 return $items;
94 }
95
96 /**
97 * Menu callback; Forwards request to user subscription form;
98 */
99 function mailman_manager_page() {
100 if (!user_access('access mailman_manager')) {
101 return t('You must be an authorized member to subscribe to mailing lists');
102 }
103 else {
104 global $user;
105 drupal_goto('user/'. $user->uid .'/mailman_manager');
106 }
107 }
108
109 function _mailman_manager_user_form(&$form_state,$account) {
110 $form = array();
111 $output = '<div class="mailman_manager">';
112 $output .= '<p>'. t('The following email address will be subscribed to the email lists:') .'<br /><strong>'. $account->mail .'</strong><br />';
113 $output .= t('If you would like to have a different email address subscribed, change your email address in the account settings tab.');
114 $lists = _mailman_manager_get_lists();
115
116 if (count($lists) == 0) {
117 $output = t('There are no lists available for subscription.');
118 }
119 else {
120 $status = 0;
121 foreach ($lists as $list) {
122 $form['list'. trim($list['lid'])] = array(
123 '#type' => 'fieldset',
124 '#title' => $list['name'],
125 '#collapsible' => TRUE
126 );
127
128 $subscrip = _mailman_manager_get_subscriptions($account->uid, $list['lid']);
129 if ($subscrip['lstatus'] == 0) {
130 $options = array('2' => t('Subscribe for digest (receive emails in a bundle)'),
131 '3' => t('Subscribe for all Mail (normal delivery)'));
132 $status++;
133 }
134 else {
135 $options = array('0' => t('Unsubscribe'),
136 '1' => t('No mail (temporarily disable delivery)'),
137 '2' => t('Subscribe for digest (receive emails in a bundle)'),
138 '3' => t('Subscribe for all Mail (normal delivery)'),
139 '4' => t('Mail password'));
140 }
141 $subscrip = _mailman_manager_get_subscriptions($account->uid, $list['lid']);
142 $form['list'. trim($list['lid'])]['options'. trim($list['lid'])] = array(
143 '#type' => 'radios',
144 '#title' => t('Change your subscription'),
145 '#options' => $options,
146 '#default_value' => $subscrip['lstatus']
147 );
148 if ($subscrip['lstatus'] == 0) {
149 $form['list'. trim($list['lid'])]['pass'. trim($list['lid'])] = array('#type' => 'textfield',
150 '#title' => t('Password for %listname (optional)', array('%listname' => $list['name'])),
151 '#size' => 15,
152 '#required' => FALSE,
153 '#default_value' => t($subscrip['lpass'])
154 );
155 }
156 if ($list['web'] || $list['webarch']) {
157 $link_output = '<p>'. t('Visit') .': ';
158 if ($list['web']) {
159 $link_output .= l(t('Mailman Interface'), $list['web']);
160 }
161 if ($list['web'] && $list['webarch']) {
162 $link_output .= ' '. t('or') .': ';
163 }
164 if ($list['webarch']) {
165 $link_output .= l($list['name'] .' '. t('archive') .'.', $list['webarch']);
166 }
167 $form['list'. trim($list['lid'])]['links'] = array('#type' => 'markup', '#value' => $link_output);
168 }
169 }
170 if ($status != 0) {
171 $output .= '<p>'. t('Your current email address is not subscribed to %status list(s).', array('%status' => $status)) .'</p>';
172 }
173 else {
174 $output .= '<p>'. t('Your current email address is currently subscribed to all lists.') .'</p>';
175 }
176 $output .= '</div>';
177 $form['lists']['oldemail'] = array(
178 '#type' => 'hidden',
179 '#default_value' => $subscrip['lmail']
180 );
181 $form['lists']['newemail'] = array(
182 '#type' => 'hidden',
183 '#default_value' => $account->mail
184 );
185
186 }
187 $form['mman_info'] = array('#type' => 'markup', '#value' => $output, '#weight' => -1);
188 $form['submit'] = array(
189 '#type' => 'submit',
190 '#value' => t('Save')
191 );
192 return $form;
193
194 }
195
196 /**
197 * Checks whether an email address is subscribed to the mailinglist
198 * when a new user signs up. If so, changes uid from 0 to the new uid
199 * in sn_subscriptions so that the user's subscription status is known
200 * when he logs in.
201 */
202 function _mailman_manager_user_form_submit($form, &$form_state) {
203 if (!is_numeric($uid = arg(1))) {
204 return false;
205 }
206 $account=user_load($uid);
207 $lists = _mailman_manager_get_lists();
208 foreach ($lists as $list) {
209 $subscrip = _mailman_manager_get_subscriptions($account->uid, $list['lid']);
210 $listno = 'options'. trim($list['lid']);
211 $query = "SELECT * FROM {mailman_users} WHERE uid = %d AND lid = %d";
212 $result = db_query($query, $account->uid, $list['lid']);
213 $subscrip = db_fetch_array($result);
214 if ($form_state['values']['pass'. trim($list['lid'])] == '') {
215 $password = $subscrip['lpass'];
216 }
217 else {
218 $password = $form_state['values']['pass'. trim($list['lid'])];
219 }
220 $form_state['values']['pass'. trim($list['lid'])] = '';
221 if ($subscrip['lstatus'] != $form_state['values'][$listno]) {
222 _mailman_manager_update_subscriptions($account->uid, $list['lid'], $form_state['values'][$listno],
223 $subscrip['lstatus'], $account->mail, $password);
224 }
225 }
226 drupal_set_message(t('Your mailing list subscriptions have been updated'));
227
228 }
229
230 function mailman_manager_admin_delete_form(&$form_state, $lid) {
231 $form = array();
232 $list = mailman_manager_get_list($lid);
233 $form['lid'] = array(
234 '#type' => 'hidden',
235 '#value' => $lid
236 );
237 $form['message'] = array('#type' => 'markup', '#value' => t('Are you sure?'));
238 $form['submit'] = array(
239 '#type' => 'submit',
240 '#value' => t('Delete !listname', array('!listname' => $list->name))
241 );
242 return $form;
243 }
244
245 function mailman_manager_admin_delete_form_submit($form, &$form_state) {
246 if (!user_access('administer mailman_manager')) {
247 return '';
248 }
249 $result = db_query("DELETE FROM {mailman_users} WHERE lid = %d", $form_state['values']['lid']);
250
251 if ($result && db_query("DELETE FROM {mailman_lists} WHERE lid = %d", $form_state['values']['lid'])) {
252 watchdog('mailman man', 'Successfully deleted Mailman list %listid', array('%listid' => $list['lid']), WATCHDOG_NOTICE);
253 drupal_goto('admin/settings/mailman_manager');
254 }
255 else {
256 watchdog('mailman man', 'Mailman list %listid deletion failed', array('%listid' => $list['lid']), WATCHDOG_ERROR);
257 drupal_set_message('Error deleting Mailing list', 'error');
258 }
259 }
260
261 function mailman_manager_get_list($id) {
262 return db_fetch_object(db_query("SELECT * FROM {mailman_lists} WHERE lid = %d", $id));
263 }
264
265
266 function mailman_manager_admin_form(&$form_state, $lid = false) {
267 $form = array();
268 if ($lid) {
269 $list = mailman_manager_get_list($lid);
270 $form['lid'] = array(
271 '#type' => 'hidden',
272 '#value' => $lid
273 );
274 }
275
276 $form['name'] = array(
277 '#title' => 'Mailing List name',
278 '#default_value' => $list->name,
279 '#type' => 'textfield',
280 '#required' => true,
281 );
282 $form['reqaddress'] = array(
283 '#title' => t("Mailing List 'request' address"),
284 '#default_value' => $list->command,
285 '#description' => t('Commands are sent here'),
286 '#type' => 'textfield',
287 '#required' => true
288 );
289 $form['adminaddress'] = array(
290 '#title' => t("Mailing List 'admin' address"),
291 '#default_value' => $list->admin,
292 '#description' => t('(Optional. admin is used for BCC)'),
293 '#type' => 'textfield',
294 );
295 $form['webaddress'] = array(
296 '#title' => t('Mailing list web address for users'),
297 '#default_value' => $list->web,
298 '#description' => t('http://...' ) . t("Leave empty if hidden."),
299 '#type' => 'textfield',
300 );
301 $form['webarchive'] = array(
302 '#title' => t('Mailing list web archive address for users'),
303 '#default_value' => $list->webarch,
304 '#description' => t('http://.... ') . t('Leave empty if hidden.'),
305 '#type' => 'textfield',
306 );
307
308 $form['Submit'] = array(
309 '#type' => 'submit',
310 '#value' => ($lid ? t('Save') : t('Add')),
311 );
312 return $form;
313
314 }
315
316 function mailman_manager_admin_form_validate($form, &$form_state) {
317 //Check name is unique
318 $result = db_query("SELECT COUNT(*) from {mailman_lists} WHERE name = '%s'". ($form_state['values']['lid'] ? ' AND lid <> %d' : ''), $form_state['values']['name'], $form_state['values']['lid']);
319 $num_rows = db_result($result);
320 if ($num_rows != '0') {
321 form_set_error('name', 'Name already in use');
322 }
323
324 if ($form_state['values']['reqaddress'] && !valid_email_address($form_state['values']['reqaddress'])) {
325 form_set_error('reqaddress', t('"%reqaddress" is not a valid email address', array('%reqaddress' => $form_state['values']['reqaddress'])));
326 }
327
328 if ($form_state['values']['adminaddress'] && !valid_email_address($form_state['values']['adminaddress'])) {
329 form_set_error('adminaddress', t('"%adminaddress" is not a valid email address', array('%adminaddress' => $form_state['values']['adminaddress'])));
330 }
331
332 if ($form_state['values']['webaddress'] && !valid_url($form_state['values']['webaddress'])) {
333 form_set_error('webaddress', t('"%webaddress" is not a valid url', array('%webaddress' => $form_state['values']['webaddress'])));
334 }
335
336 if ($form_state['values']['webarchive'] && !valid_url($form_state['values']['webarchive'])) {
337 form_set_error('webarchive', t('"%webarchive" is not a valid url', array('%webarchive' => $form_state['values']['webarchive'])));
338 }
339
340 }
341
342 /**
343 * Save new mailing list.
344 */
345 function mailman_manager_admin_form_submit($form, &$form_state) {
346 if (!user_access('administer mailman_manager')) {
347 return '';
348 }
349 if ($form_state['values']['lid']) {
350 //Update existin
351 $query = "UPDATE {mailman_lists} SET name = '%s', command = '%s', admin = '%s', web = '%s', webarch = '%s' WHERE lid = %d";
352 $result = db_query($query,
353 $form_state['values']['name'],
354 $form_state['values']['reqaddress'],
355 $form_state['values']['adminaddress'],
356 $form_state['values']['webaddress'],
357 $form_state['values']['webarchive'],
358 $form_state['values']['lid']
359 );
360 if ($result) {
361 drupal_goto('admin/settings/mailman_manager');
362 exit;
363 }
364 }
365 else {
366 //Create new
367 $query = "INSERT INTO {mailman_lists} (name, command, admin, web, webarch) VALUES ('%s', '%s', '%s', '%s', '%s')";
368 if (db_query($query,
369 $form_state['values']['name'],
370 $form_state['values']['reqaddress'],
371 $form_state['values']['adminaddress'],
372 $form_state['values']['webaddress'],
373 $form_state['values']['webarchive'])) {
374 $message = 'New Mailman list %name successfully created';
375 watchdog('mailman man', $message, array('%name' => $name), WATCHDOG_NOTICE);
376 drupal_goto('admin/settings/mailman_manager');
377 }
378 else {
379 $message = 'Error in creating new Mailman list %name';
380 watchdog('mailman man', $message, array('%name' => $name), WATCHDOG_ERROR);
381 return t($message, array('%name' => $name));;
382 }
383 }
384 }
385
386 /**
387 * Prepare the mailing list admin form.
388 */
389 function _mailman_manager_admin_display() {
390 if (!user_access('administer mailman_manager')) {
391 return '';
392 }
393 $output = '';
394
395 $headers = array(array('data' => t('ID'), 'field' => 'lid', 'sort' => 'asc'),
396 array('data' => t('Name'), 'field' => 'name'),
397 array('data' => t('Request Address'), 'field' => 'command'),
398 );
399
400
401 $query = "SELECT * from {mailman_lists}";
402 $query .= tablesort_sql($headers);
403
404 $num_per_page = 15;
405 $result = pager_query($query, $num_per_page);
406 $lists = array();
407 while ($list = db_fetch_array($result)) {
408 unset($list['web']);
409 unset($list['webarch']);
410 unset($list['admin']);
411 $list['edit'] = l(t('Edit'), 'admin/settings/mailman_manager/edit/'. $list['lid']);
412 $list['delete'] = l(t('Delete'), 'admin/settings/mailman_manager/delete/'. $list['lid']);
413 $lists[] = $list;
414 }
415
416 $output .= theme('table', $headers, $lists);
417 $output .= theme('pager', $num_per_page);
418
419 $output .= l(t('Add new mailing list'), 'admin/settings/mailman_manager/add');
420
421 return $output;
422
423 }
424
425 /**
426 * Return array of objects of current mailing lists.
427 */
428 function _mailman_manager_get_lists() {
429 $result = db_query("SELECT * FROM {mailman_lists}");
430 $lists = array();
431 while ($list = db_fetch_array($result)) {
432 $lists[] = $list;
433 }
434 return $lists;
435 }
436
437 /**
438 * Return array of user's subscriptions to mailing lists.
439 */
440 function _mailman_manager_get_subscriptions($uid, $lid) {
441 $query = "SELECT * FROM {mailman_users} WHERE uid = %d AND lid = %d";
442 $result = db_query($query, $uid, $lid);
443 $result = db_fetch_array($result);
444 //If there are no entries for this user then set subscriptions to zero;
445 //and return no mail button option for display;
446 if (!$result || count($result) == 0) {
447 $query = "INSERT INTO {mailman_users} (uid, lid, lstatus) VALUES (%d, %d, %d)";
448 db_query($query, $uid, $lid, 0);
449 $result = array('uid' => $uid, 'lid' => $lid, 'lstatus' => 0);
450 }
451
452 return $result;
453 }
454
455 /**
456 * Update user's subscriptions to mailing lists.
457 */
458 function _mailman_manager_update_subscriptions($uid, $lid, $lstatus, $oldstatus, $mail, $password) {
459 // Do not update status for 'mail password':
460
461
462 if ($lstatus != 4) {
463 $query = "UPDATE {mailman_users} SET lstatus = %d WHERE uid = %d AND lid = %d";
464 db_query($query, $lstatus, $uid, $lid);
465 }
466
467
468 switch ($lstatus) {
469
470 // Unsubscribe selected;
471 case 0:
472 $command = 'unsubscribe '. $password .' address='. $mail;
473 _mailman_manager_setdelivery($uid, $lid, $mail, $command);
474 watchdog('mailman man', 'User %uid unsubscribed from list %lid', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
475 break;
476
477
478 // No email selected;
479 case 1:
480 $command = 'set authenticate '. $password .' address='. $mail ."\n";
481 $command .= 'set delivery off';
482 _mailman_manager_setdelivery($uid, $lid, $mail, $command);
483 watchdog('mailman man', 'Subscription to list %lid for user %uid changed to no mail', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
484 break;
485
486 //Digest selected;
487 case 2:
488 if ($oldstatus == 0) {
489 _mailman_manager_subscribe($uid, $lid, $mail, 'digest', $password);
490 }
491 else {
492 $command = 'set authenticate '. $password .' address='. $mail ."\n";
493 $command .= "set delivery on\n";
494 $command .= "set digest plain";
495 _mailman_manager_setdelivery($uid, $lid, $mail, $command);
496 watchdog('mailman man', 'Subscription to list %lid for user %uid changed to digest', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
497 }
498 break;
499
500 //All mail selected;
501 case 3:
502 if ($oldstatus == 0) {
503 _mailman_manager_subscribe($uid, $lid, $mail, 'nodigest', $password);
504 }
505 else {
506 $command = 'set authenticate '. $password .' address='. $mail ."\n";
507 $command .= "set delivery on\n";
508 $command .= "set digest off";
509 _mailman_manager_setdelivery($uid, $lid, $mail, $command);
510 watchdog('mailman man', 'Subscription to list %lid for user %uid changed to all mail', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
511 }
512 break;
513
514 //mail pwd selected;
515 case 4:
516 if ($oldstatus == 0) {
517 return;
518 }
519 else {
520 $command = 'password address='. $mail ."\n";
521 _mailman_manager_setdelivery($uid, $lid, $mail, $command);
522 watchdog('mailman man', 'Password for list %lid for user %uid sent by mail', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
523 }
524 break;
525
526 }
527 return;
528 }
529
530 /**
531 * Create a new subscription by sending request email to Mailman.
532 */
533 function _mailman_manager_subscribe($uid, $lid, $mail, $digest, $password) {
534 $params = array();
535 $query = 'SELECT * FROM {mailman_lists} WHERE lid = %d';
536 $result = db_query($query, $lid);
537 $list = db_fetch_array($result);
538 $commandaddress = $list['command'];
539 $adminaddress = $list['admin'];
540 if ($password == "") {
541 $password = _mailman_manager_rand_str(5);
542 $password .= trim($uid) . substr($mail, 0, 1);
543 }
544 $params['command'] = 'subscribe '. $password .' '. $digest .' address='. trim($mail);
545
546 // If the adminaddress was given, use BCC
547 if ($adminaddress != "") {
548 $params['bcc'] = $adminaddress;
549 }
550 $mailsuccess = drupal_mail('mailman_manager', 'subscribe', $commandaddress, language_default(), $params);
551 $query = "UPDATE {mailman_users} SET lmail = '%s', lpass = '%s' WHERE uid = %d AND lid = %d";
552 if ($mailsuccess['result'] && db_query($query, $mail, $password, $uid, $lid)) {
553 watchdog('mailman man', 'New subscription to list %lid for user %uid completed successfully.', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_NOTICE);
554 }
555 else {
556 watchdog('mailman man', 'New subscription to list %lid for user %uid failed.', array('%lid' => $lid, '%uid' => $uid), WATCHDOG_ERROR);
557 }
558 return;
559 }
560
561 /**
562 * Update settings for a subscription by sending request email to Mailman.
563 */
564 function _mailman_manager_setdelivery($uid, $lid, $mail, $command) {
565 $params = array('command' => $command);
566 $query = "SELECT * FROM {mailman_lists} WHERE lid = %d";
567 $result = db_query($query, $lid);
568 $list = db_fetch_array($result);
569 $commandaddress = $list['command'];
570 $adminaddress = $list['admin'];
571
572 // If the adminaddress was given, use BCC
573 if ($adminaddress != '') {
574 $params['bcc'] = $adminaddress;
575 }
576 watchdog('mailman man', 'Mail command sent to Mailman to: %commandaddress. Command: %command', array('%commandaddress' => $commandaddress, '%command' => $command), WATCHDOG_NOTICE);
577 drupal_mail('mailman_manager', 'notify', $commandaddress, language_default(), $params);
578 return;
579 }
580
581 function mailman_manager_mail($key, &$message, $params) {
582 if ($params['bcc']) {
583 $massage['headers']['bcc'] = $params['bcc'];
584 }
585 $message['subject'] = '';
586 $message['body'][] = $params['command'];
587 }
588
589 /**
590 * Generation of five character random text string for Mailman password.
591 */
592 function _mailman_manager_rand_str($size) {
593 $feed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
594 for ($i = 0; $i < $size; $i++) {
595 $rand_str .= substr($feed, rand(0, strlen($feed) - 1), 1);
596 }
597 return $rand_str;
598 }

  ViewVC Help
Powered by ViewVC 1.1.2