]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/user/fo_posting.pl
3 ################################################################################
5 # File: user/fo_posting.pl #
7 # Authors: André Malo <nd@o3media.de>, 2001-01-25 #
9 # Description: Accept new postings, display "Neue Nachricht" page #
11 ################################################################################
14 use vars
qw($Bin $Shared $Script %subhash $httpurl $flocked);
17 my $null = $0; $null =~ s/\\/\//g; # for win :-(
18 ($Bin) = ($null =~ /^(.*)\/.*$/)? $1 : '.';
19 $Shared = "$Bin/../shared";
20 ($Script) = ($null =~ /^.*\/(.*)$/)? $1 : $null;
23 use CGI::Carp qw(fatalsToBrowser);
27 use Encode
::Plain
; $Encode::Plain
::utf8
= 1;
32 use Posting
::_lib
qw(get_all_threads get_message_node get_message_header hr_time);
35 use Template
::Posting
;
37 use CGI
qw(param header);
40 print header
(-type
=> 'text/html');
42 our $conf = read_script_conf
($Bin, $Shared, $Script);
44 our $show_posting = $conf -> {show
} -> {Posting
};
45 our $assign = $show_posting -> {assign
};
46 our $formmust = $show_posting -> {form
} -> {must
};
47 our $formdata = $show_posting -> {form
} -> {data
};
48 our $formact = $show_posting -> {form
} -> {action
};
49 our $template = new Template
$show_posting -> {templateFile
};
51 our ($failed, %dparam, $threads, $last_thread, $last_message, $ftid, $fmid, $flocked);
53 sub forum_filename
() {$conf -> {files
} -> {forum
};}
54 sub message_path
() {$conf -> {files
} -> {messagePath
};}
56 ################################
58 # Formfelder ausfuellen (Namen)
59 for (qw(posterBody uniqueID followUp quoteChar userID posterName posterEmail posterCategory posterSubject posterURL posterImage)) {
60 $pars -> {$formdata -> {$_} -> {assign
} -> {name
}} = plain
($formdata -> {$_} -> {name
});}
62 my $checked = &check_param
;
64 unless (exists ($subhash {$checked})) {
65 &print_fatal
($assign -> {unknownError
});}
68 unless ($checked eq 'newThread') {
69 $checked = &check_reply_dupe
() || $checked;}
71 unless (exists ($subhash {$checked})) {
72 &print_fatal
($assign -> {unknownError
});}
74 &{$subhash {$checked}};}
77 violent_unlock_file
(forum_filename
) unless (write_unlock_file
(forum_filename
));}}
79 # ====================================================
80 # end of main / Funktionen
81 # ====================================================
84 ### check_reply_dupe () ########################################################
86 # Reply moeglich? Doppelposting?
89 # Return: Dupe check result
90 # 'Dupe' - Posting is a dupe
93 sub check_reply_dupe
() {
96 unless ($stat = write_lock_file
(forum_filename
)) {
99 violent_unlock_file
(forum_filename
);
105 my ($i, %msg, %unids);
109 ($threads, $last_thread, $last_message, undef, my $unids) = get_all_threads
(forum_filename
, 1, 0);
110 ($ftid,$fmid) = split /;/,$dparam{$formdata -> {followUp
} -> {name
}},2;
112 # Thread existiert nicht
113 if (exists($dparam{$formdata -> {followUp
} -> {name
}})) {
114 return 'noReply' unless (exists($threads -> {$ftid}));
116 # nur nicht geloeschte Messages beachten
117 for ($i=0; $i < @
{$threads -> {$ftid}}; $i++) {
118 if ($threads -> {$ftid} -> [$i] -> {deleted
}) {
119 $i+=$threads -> {$ftid} -> [$i] -> {answers
};}
122 $msg{$threads -> {$ftid} -> [$i] -> {mid
}}=$i;}}
124 # Message existiert nicht
125 if (exists($dparam{$formdata -> {followUp
} -> {name
}})) {
126 return 'noReply' unless (exists($msg{$fmid}));}
128 %unids = map {$_ => 1} @
{$threads -> {$ftid} -> [$msg{$fmid}] -> {unids
}};
130 %unids = map {$_ => 1} @
$unids;
134 return 'Dupe' if (exists ($unids{$dparam{$formdata -> {uniqueID
} -> {name
}}}));
140 ################################
143 # Eroeffnungsposting speichern
144 ################################
149 my $pars = {author
=> $dparam {$formdata -> {posterName
} -> {name
}},
150 email
=> $dparam {$formdata -> {posterEmail
} -> {name
}},
151 category
=> $dparam {$formdata -> {posterCategory
} -> {name
}},
152 subject
=> $dparam {$formdata -> {posterSubject
} -> {name
}},
153 body
=> $dparam {$formdata -> {posterBody
} -> {name
}},
154 homepage
=> $dparam {$formdata -> {posterURL
} -> {name
}},
155 image
=> $dparam {$formdata -> {posterImage
} -> {name
}},
157 uniqueID
=> $dparam {$formdata -> {uniqueID
} -> {name
}},
158 ip
=> $ENV{REMOTE_ADDR
},
159 forumFile
=> forum_filename
,
160 messagePath
=> message_path
,
161 lastThread
=> $last_thread,
162 lastMessage
=> $last_message,
163 parsedThreads
=> $threads,
165 quoteChars
=> toUTF8
('»» '),
166 messages
=> $conf -> {template
} -> {messages
}};
168 my ($stat, $xml, $mid) = write_posting
($pars);
169 violent_unlock_file
(forum_filename
) unless (write_unlock_file
(forum_filename
));
173 print "Och noe...: $stat";}
176 my $thx = $show_posting -> {thanx
};
178 print ${$template -> scrap
($assign -> {docThx
},
179 {$thx -> {author
} => plain
($dparam {$formdata -> {posterName
} -> {name
}}),
180 $thx -> {email
} => plain
($dparam {$formdata -> {posterEmail
} -> {name
}}),
181 $thx -> {time} => plain
(hr_time
($time)),
182 $thx -> {body
} => message_as_HTML
($xml, $template,
185 $thx -> {category
} => plain
($dparam {$formdata -> {posterCategory
} -> {name
}}),
186 $thx -> {home
} => plain
($dparam {$formdata -> {posterURL
} -> {name
}}),
187 $thx -> {image
} => plain
($dparam {$formdata -> {posterImage
} -> {name
}}),
188 $thx -> {subject
} => plain
($dparam {$formdata -> {posterSubject
} -> {name
}})})};
193 ################################
196 # Antwortposting speichern
197 ################################
203 my $pars = {author
=> $dparam {$formdata -> {posterName
} -> {name
}},
204 email
=> $dparam {$formdata -> {posterEmail
} -> {name
}},
205 category
=> $dparam {$formdata -> {posterCategory
} -> {name
}},
206 subject
=> $dparam {$formdata -> {posterSubject
} -> {name
}},
207 body
=> $dparam {$formdata -> {posterBody
} -> {name
}},
208 homepage
=> $dparam {$formdata -> {posterURL
} -> {name
}},
209 image
=> $dparam {$formdata -> {posterImage
} -> {name
}},
211 uniqueID
=> $dparam {$formdata -> {uniqueID
} -> {name
}},
212 ip
=> $ENV{REMOTE_ADDR
},
213 parentMessage
=> $fmid,
215 forumFile
=> forum_filename
,
216 messagePath
=> message_path
,
217 lastThread
=> $last_thread,
218 lastMessage
=> $last_message,
219 parsedThreads
=> $threads,
221 quoteChars
=> toUTF8
('»» '),
222 messages
=> $conf -> {template
} -> {messages
}};
224 ($stat, my $xml, my $mid) = write_posting
($pars);
225 violent_unlock_file
(forum_filename
) unless (write_unlock_file
(forum_filename
));
229 print "Och noe...: $stat";}
232 my $thx = $show_posting -> {thanx
};
234 print ${$template -> scrap
($assign -> {docThx
},
235 {$thx -> {author
} => plain
($dparam {$formdata -> {posterName
} -> {name
}}),
236 $thx -> {email
} => plain
($dparam {$formdata -> {posterEmail
} -> {name
}}),
237 $thx -> {time} => plain
(hr_time
($time)),
238 $thx -> {body
} => message_as_HTML
($xml, $template,
241 $thx -> {category
} => plain
($dparam {$formdata -> {posterCategory
} -> {name
}}),
242 $thx -> {home
} => plain
($dparam {$formdata -> {posterURL
} -> {name
}}),
243 $thx -> {image
} => plain
($dparam {$formdata -> {posterImage
} -> {name
}}),
244 $thx -> {subject
} => plain
($dparam {$formdata -> {posterSubject
} -> {name
}})})};}
247 ################################
250 # HTML fuer Eroeffnungsposting
251 ################################
254 my $list = [map {{$assign -> {optval
} => plain
($_)}} @
{$formdata -> {posterCategory
} -> {values}}];
256 # spaeter kommen noch userspezifische Daten dazu...
257 print ${$template -> scrap
($assign -> {docNew
},
258 {$formdata->{uniqueID
} ->{assign
}->{value
} => plain
(unique_id
),
259 $formdata->{quoteChar
} ->{assign
}->{value
} => 'ÿ'.plain
(toUTF8
('»» ')),
260 $formact->{post
}->{assign
} => $formact->{post
}->{url
},
261 $formdata->{posterCategory
}->{assign
}->{value
} => $template->list ($assign -> {option
}, $list)
265 ################################
269 ################################
271 sub no_reply
() {&print_fatal
($assign -> {noReply
});}
272 sub dupe_posting
() {&print_fatal
($assign -> {dupe
});}
273 sub missing_key
() {&print_fatal
($assign -> {wrongPar
});}
274 sub unexpected_key
() {&print_fatal
($assign -> {wrongPar
});}
275 sub unknown_encoding
() {&print_fatal
($assign -> {wrongCode
});}
277 if ($formdata -> {$failed} -> {errorType
} eq 'repeat') {
278 &print_error
($formdata -> {$failed} -> {assign
} -> {tooShort
},
279 $formdata -> {$failed} -> {minlength
});}
282 &print_fatal
($formdata -> {$failed} -> {assign
} -> {tooShort
});}
286 if ($formdata -> {$failed} -> {errorType
} eq 'repeat') {
287 &print_error
($formdata -> {$failed} -> {assign
} -> {tooLong
},
288 $formdata -> {$failed} -> {maxlength
});}
291 &print_fatal
($formdata -> {$failed} -> {assign
} -> {tooLong
});}
294 sub wrong_mail
() {print_error
($formdata -> {$failed} -> {assign
} -> {wrong
});}
295 sub occupied
() {print_error
($assign -> {occupied
});}
297 ################################
300 # fatale Fehlerausgabe
301 ################################
303 sub print_fatal
($) {
304 print ${$template -> scrap
($assign -> {docFatal
},
305 {$assign -> {errorMessage
} => $template -> insert
($_[0])
309 ################################
312 # Fehlerausgabe, Moeglichkeit
314 ################################
316 sub print_error
($;$) {
318 print ${$template -> scrap
($assign -> {docError
},
319 {$assign -> {errorMessage
} => $template -> insert
($_[0]),
320 $assign -> {charNum
} => $_[1]
324 ################################
327 # Subject und Category besorgen
328 # (wenn noch nicht vorhanden)
329 ################################
331 sub fetch_subject
() {
333 my %must = map {$_ => 1} @
{$formmust -> {exists $dparam{$formdata -> {followUp
} -> {name
}}?
'reply':'new'}};
335 if ( ($must{posterCategory
} and not exists ($dparam{$formdata -> {posterCategory
} -> {name
}})) or
336 ($must{posterSubject
} and not exists ($dparam{$formdata -> {posterSubject
} -> {name
}})))
338 my $filename = message_path
.'t'.$ftid.'.xml';
340 if (-f
$filename and lock_file
($filename))
342 my $xml = new XML
::DOM
::Parser
-> parsefile
($filename);
343 violent_unlock_file
($filename) unless unlock_file
($filename);
345 my $mnode = get_message_node
($xml, "t$ftid", "m$fmid");
346 my $header = get_message_header
($mnode);
348 $dparam{$formdata -> {posterCategory
} -> {name
}} = $header -> {category
};
349 $dparam{$formdata -> {posterSubject
} -> {name
}} = $header -> {subject
};
354 ################################
358 # (bereits vorhandene Formdaten)
359 ################################
364 my $list = [map {{$assign -> {optval
} => plain
($_),
365 (($_ eq $dparam{$formdata -> {posterCategory
} -> {name
}})?
($assign -> {optsel
} => 1):())}}
366 @
{$formdata -> {posterCategory
} -> {values}}];
368 $pars -> {$formdata->{posterCategory
}->{assign
}->{value
}} = $template->list ($assign -> {option
}, $list);
369 $pars -> {$formact ->{post
}->{assign
}} = $formact->{post
}->{url
};
370 $pars -> {$formdata->{quoteChar
}->{assign
}->{value
}} = 'ÿ'.plain
($dparam {$formdata -> {quoteChar
} -> {name
}} or '');
372 # Formfelder ausfuellen (Werte)
373 for (qw(uniqueID userID followUp posterName posterEmail posterSubject posterBody posterURL posterImage)) {
374 $pars -> {$formdata->{$_}->{assign
}->{value
}} = plain
($dparam {$formdata -> {$_} -> {name
}});}
377 ################################
380 # CGI-Parameter decodieren
381 # (rudimentaerer UTF8-support)
382 ################################
384 sub decode_param
() {
385 my $code = param
($formdata -> {quoteChar
} -> {name
});
388 # UTF-8 ([hoechst-]wahrscheinlich)
389 if ($code =~ /^\303\277/) {
395 $dparam{$_} = $array[0];}
398 $dparam{$_} = \
@array;}}}
400 # Latin 1 (hoffentlich - eigentlich ist es gar keine Codierung...)
401 elsif ($code =~ /^\377/) {
406 $dparam{$_} = toUTF8
($array[0]);}
409 $dparam{$_} = [map {toUTF8
($_)} @array];}}}
411 # unbekannte Codierung
415 # ersten beiden Zeichen der Quotechars loeschen (Indikator [ÿ (als UTF8)])
416 $dparam {$formdata -> {quoteChar
} -> {name
}} = ($dparam {$formdata -> {quoteChar
} -> {name
}} =~ /..(.*)/)[0];
418 delete $dparam {$formdata -> {posterURL
} -> {name
}}
419 unless ($dparam {$formdata -> {posterURL
} -> {name
}} =~ /$httpurl/);
421 delete $dparam {$formdata -> {posterImage
} -> {name
}}
422 unless ($dparam {$formdata -> {posterImage
} -> {name
}} =~ /$httpurl/);
424 # Codierung erkannt, alles klar
428 ################################
431 # CGI-Parameter pruefen
432 ################################
435 my %gotKeys = map {($_ => 1)} param
;
436 my $numGotKeys = keys %gotKeys;
438 # Threaderoeffnung, Ersteingabe (leere Seite)
439 return 'newThread' if ($numGotKeys == 0 or
440 (($numGotKeys == 1) and ($gotKeys {$formdata -> {userID
} -> {name
}})));
442 # =======================================================
443 # ab hier steht fest, wir haben ein ausgefuelltes
446 # 1. Umrechnungshash bauen (CGI-Key => Identifier)
447 # 2. alle must-keys vorhanden?
448 # 3. zuviele Parameter uebermittelt?
449 # 4. entsprechen die Daten den Anforderungen?
450 # (alle, nicht nur die must-Daten)
454 my %name = map {($formdata -> {$_} -> {name
} => $_)} keys %$formdata;
459 foreach (@
{$formmust -> {$gotKeys {$formdata -> {followUp
} -> {name
}}?
'reply':'new'}}) {
460 return 'missingKey' unless ($gotKeys {$formdata -> {$_} -> {name
}});
466 $failed = $name {$_};
467 return 'unexpectedKey' unless (exists ($name {$_}));
472 return 'unknownEncoding' unless (decode_param
);
474 foreach (keys %dparam) {
475 $failed = $name {$_};
477 return 'tooLong' if (length($dparam{$_}) > $formdata -> {$name {$_}} -> {maxlength
});
478 return 'tooShort' if (@
{[$dparam{$_} =~ /(\S)/g]} < $formdata -> {$name {$_}} -> {minlength
});
479 return 'wrongMail' if ($formdata -> {$name{$_}} -> {type
} eq 'email' and length ($dparam{$_}) and not is_mail_address
($dparam{$_}));
483 return $gotKeys {$formdata -> {followUp
} -> {name
}}?
'gotReply':'gotNew';
486 # ====================================================
488 # ====================================================
491 %subhash = (newThread
=> \
&new_thread
,
492 missingKey
=> \
&missing_key
,
493 unexpectedKey
=> \
&unexpected_key
,
494 unknownEncoding
=> \
&unknown_encoding
,
495 tooShort
=> \
&too_short
,
496 tooLong
=> \
&too_long
,
497 wrongMail
=> \
&wrong_mail
,
498 Occupied
=> \
&occupied
,
499 Dupe
=> \
&dupe_posting
,
500 noReply
=> \
&no_reply
,
501 gotReply
=> \
&got_reply
,
505 # Die RFC-gerechte URL-Erkennung ist aus dem Forum
506 # (thx2Cheatah - wo auch immer er sie (in der Form) her hat :-)
507 my $lowalpha = '(?:[a-z])';
508 my $hialpha = '(?:[A-Z])';
509 my $alpha = "(?:$lowalpha|$hialpha)";
510 my $digit = '(?:\d)';
511 my $safe = '(?:[$_.+-])';
512 my $hex = '(?:[\dA-Fa-f])';
513 my $escape = "(?:%$hex$hex)";
514 my $digits = '(?:\d+)';
515 my $alphadigit = "(?:$alpha|\\d)";
517 # URL schemeparts for ip based protocols:
518 my $port = "(?:$digits)";
519 my $hostnumber = "(?:$digits\\.$digits\\.$digits\\.$digits)";
520 my $toplabel = "(?:(?:$alpha(?:$alphadigit|-)*$alphadigit)|$alpha)";
521 my $domainlabel = "(?:(?:$alphadigit(?:$alphadigit|-)*$alphadigit)|$alphadigit)";
522 my $hostname = "(?:(?:$domainlabel\\.)*$toplabel)";
523 my $host = "(?:(?:$hostname)|(?:$hostnumber))";
524 my $hostport = "(?:(?:$host)(?::$port)?)";
526 my $httpuchar = "(?:(?:$alpha|$digit|$safe|(?:[!*\',]))|$escape)";
527 my $hsegment = "(?:(?:$httpuchar|[;:\@&=~])*)";
528 my $search = "(?:(?:$httpuchar|[;:\@&=~])*)";
529 my $hpath = "(?:$hsegment(?:/$hsegment)*)";
531 # das alles ergibt eine gueltige URL :-)
532 $httpurl = "^(?:https?://$hostport(?:/$hpath(?:\\?$search)?)?)\$";
535 # ====================================================
536 # end of fo_posting.pl
537 # ====================================================
patrick-canterino.de