OLD | NEW |
| (Empty) |
1 # Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org> | |
2 # | |
3 # This program is free software; you can redistribute it and/or modify | |
4 # it under the terms of the GNU General Public License as published by | |
5 # the Free Software Foundation; either version 2 of the License, or | |
6 # (at your option) any later version. | |
7 # | |
8 # This program is distributed in the hope that it will be useful, | |
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 # GNU General Public License for more details. | |
12 # | |
13 # You should have received a copy of the GNU General Public License | |
14 # along with this program. If not, see <https://www.gnu.org/licenses/>. | |
15 | |
16 package Dpkg::Control::FieldsCore; | |
17 | |
18 use strict; | |
19 use warnings; | |
20 | |
21 our $VERSION = '1.00'; | |
22 | |
23 use Exporter qw(import); | |
24 use Dpkg::Gettext; | |
25 use Dpkg::ErrorHandling; | |
26 use Dpkg::Control::Types; | |
27 use Dpkg::Checksums; | |
28 | |
29 our @EXPORT = qw(field_capitalize field_is_official field_is_allowed_in | |
30 field_transfer_single field_transfer_all | |
31 field_list_src_dep field_list_pkg_dep field_get_dep_type | |
32 field_get_sep_type | |
33 field_ordered_list field_register | |
34 field_insert_after field_insert_before | |
35 FIELD_SEP_UNKNOWN FIELD_SEP_SPACE FIELD_SEP_COMMA | |
36 FIELD_SEP_LINE); | |
37 | |
38 use constant { | |
39 ALL_PKG => CTRL_INFO_PKG | CTRL_INDEX_PKG | CTRL_PKG_DEB | CTRL_FILE_STATUS, | |
40 ALL_SRC => CTRL_INFO_SRC | CTRL_INDEX_SRC | CTRL_PKG_SRC, | |
41 ALL_CHANGES => CTRL_FILE_CHANGES | CTRL_CHANGELOG, | |
42 }; | |
43 | |
44 use constant { | |
45 FIELD_SEP_UNKNOWN => 0, | |
46 FIELD_SEP_SPACE => 1, | |
47 FIELD_SEP_COMMA => 2, | |
48 FIELD_SEP_LINE => 4, | |
49 }; | |
50 | |
51 # The canonical list of fields | |
52 | |
53 # Note that fields used only in dpkg's available file are not listed | |
54 # Deprecated fields of dpkg's status file are also not listed | |
55 our %FIELDS = ( | |
56 'Architecture' => { | |
57 allowed => (ALL_PKG | ALL_SRC | CTRL_FILE_CHANGES) & (~CTRL_INFO_SRC), | |
58 separator => FIELD_SEP_SPACE, | |
59 }, | |
60 'Binary' => { | |
61 allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES, | |
62 # XXX: This field values are separated either by space or comma | |
63 # depending on the context. | |
64 separator => FIELD_SEP_SPACE | FIELD_SEP_COMMA, | |
65 }, | |
66 'Binary-Only' => { | |
67 allowed => ALL_CHANGES, | |
68 }, | |
69 'Breaks' => { | |
70 allowed => ALL_PKG, | |
71 separator => FIELD_SEP_COMMA, | |
72 dependency => 'union', | |
73 dep_order => 7, | |
74 }, | |
75 'Bugs' => { | |
76 allowed => (ALL_PKG | CTRL_INFO_SRC | CTRL_FILE_VENDOR) & (~CTRL_INFO_PK
G), | |
77 }, | |
78 'Build-Conflicts' => { | |
79 allowed => ALL_SRC, | |
80 separator => FIELD_SEP_COMMA, | |
81 dependency => 'union', | |
82 dep_order => 4, | |
83 }, | |
84 'Build-Conflicts-Arch' => { | |
85 allowed => ALL_SRC, | |
86 separator => FIELD_SEP_COMMA, | |
87 dependency => 'union', | |
88 dep_order => 5, | |
89 }, | |
90 'Build-Conflicts-Indep' => { | |
91 allowed => ALL_SRC, | |
92 separator => FIELD_SEP_COMMA, | |
93 dependency => 'union', | |
94 dep_order => 6, | |
95 }, | |
96 'Build-Depends' => { | |
97 allowed => ALL_SRC, | |
98 separator => FIELD_SEP_COMMA, | |
99 dependency => 'normal', | |
100 dep_order => 1, | |
101 }, | |
102 'Build-Depends-Arch' => { | |
103 allowed => ALL_SRC, | |
104 separator => FIELD_SEP_COMMA, | |
105 dependency => 'normal', | |
106 dep_order => 2, | |
107 }, | |
108 'Build-Depends-Indep' => { | |
109 allowed => ALL_SRC, | |
110 separator => FIELD_SEP_COMMA, | |
111 dependency => 'normal', | |
112 dep_order => 3, | |
113 }, | |
114 'Built-For-Profiles' => { | |
115 allowed => ALL_PKG | CTRL_FILE_CHANGES, | |
116 separator => FIELD_SEP_SPACE, | |
117 }, | |
118 'Built-Using' => { | |
119 allowed => ALL_PKG, | |
120 separator => FIELD_SEP_COMMA, | |
121 dependency => 'union', | |
122 dep_order => 10, | |
123 }, | |
124 'Changed-By' => { | |
125 allowed => CTRL_FILE_CHANGES, | |
126 }, | |
127 'Changes' => { | |
128 allowed => ALL_CHANGES, | |
129 }, | |
130 'Closes' => { | |
131 allowed => ALL_CHANGES, | |
132 separator => FIELD_SEP_SPACE, | |
133 }, | |
134 'Conffiles' => { | |
135 allowed => CTRL_FILE_STATUS, | |
136 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE, | |
137 }, | |
138 'Config-Version' => { | |
139 allowed => CTRL_FILE_STATUS, | |
140 }, | |
141 'Conflicts' => { | |
142 allowed => ALL_PKG, | |
143 separator => FIELD_SEP_COMMA, | |
144 dependency => 'union', | |
145 dep_order => 6, | |
146 }, | |
147 'Date' => { | |
148 allowed => ALL_CHANGES, | |
149 }, | |
150 'Depends' => { | |
151 allowed => ALL_PKG, | |
152 separator => FIELD_SEP_COMMA, | |
153 dependency => 'normal', | |
154 dep_order => 2, | |
155 }, | |
156 'Description' => { | |
157 allowed => ALL_PKG | CTRL_FILE_CHANGES, | |
158 }, | |
159 'Directory' => { | |
160 allowed => CTRL_INDEX_SRC, | |
161 }, | |
162 'Distribution' => { | |
163 allowed => ALL_CHANGES, | |
164 }, | |
165 'Enhances' => { | |
166 allowed => ALL_PKG, | |
167 separator => FIELD_SEP_COMMA, | |
168 dependency => 'union', | |
169 dep_order => 5, | |
170 }, | |
171 'Essential' => { | |
172 allowed => ALL_PKG, | |
173 }, | |
174 'Filename' => { | |
175 allowed => CTRL_INDEX_PKG, | |
176 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE, | |
177 }, | |
178 'Files' => { | |
179 allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES, | |
180 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE, | |
181 }, | |
182 'Format' => { | |
183 allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES, | |
184 }, | |
185 'Homepage' => { | |
186 allowed => ALL_SRC | ALL_PKG, | |
187 }, | |
188 'Installed-Size' => { | |
189 allowed => ALL_PKG & ~CTRL_INFO_PKG, | |
190 }, | |
191 'Installer-Menu-Item' => { | |
192 allowed => ALL_PKG, | |
193 }, | |
194 'Kernel-Version' => { | |
195 allowed => ALL_PKG, | |
196 }, | |
197 'Origin' => { | |
198 allowed => (ALL_PKG | ALL_SRC) & (~CTRL_INFO_PKG), | |
199 }, | |
200 'Maintainer' => { | |
201 allowed => CTRL_PKG_DEB | ALL_SRC | ALL_CHANGES, | |
202 }, | |
203 'Multi-Arch' => { | |
204 allowed => ALL_PKG, | |
205 }, | |
206 'Package' => { | |
207 allowed => ALL_PKG, | |
208 }, | |
209 'Package-List' => { | |
210 allowed => ALL_SRC & ~CTRL_INFO_SRC, | |
211 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE, | |
212 }, | |
213 'Package-Type' => { | |
214 allowed => ALL_PKG, | |
215 }, | |
216 'Parent' => { | |
217 allowed => CTRL_FILE_VENDOR, | |
218 }, | |
219 'Pre-Depends' => { | |
220 allowed => ALL_PKG, | |
221 separator => FIELD_SEP_COMMA, | |
222 dependency => 'normal', | |
223 dep_order => 1, | |
224 }, | |
225 'Priority' => { | |
226 allowed => CTRL_INFO_SRC | CTRL_INDEX_SRC | ALL_PKG, | |
227 }, | |
228 'Provides' => { | |
229 allowed => ALL_PKG, | |
230 separator => FIELD_SEP_COMMA, | |
231 dependency => 'union', | |
232 dep_order => 9, | |
233 }, | |
234 'Recommends' => { | |
235 allowed => ALL_PKG, | |
236 separator => FIELD_SEP_COMMA, | |
237 dependency => 'normal', | |
238 dep_order => 3, | |
239 }, | |
240 'Replaces' => { | |
241 allowed => ALL_PKG, | |
242 separator => FIELD_SEP_COMMA, | |
243 dependency => 'union', | |
244 dep_order => 8, | |
245 }, | |
246 'Section' => { | |
247 allowed => CTRL_INFO_SRC | CTRL_INDEX_SRC | ALL_PKG, | |
248 }, | |
249 'Size' => { | |
250 allowed => CTRL_INDEX_PKG, | |
251 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE, | |
252 }, | |
253 'Source' => { | |
254 allowed => (ALL_PKG | ALL_SRC | ALL_CHANGES) & | |
255 (~(CTRL_INDEX_SRC | CTRL_INFO_PKG)), | |
256 }, | |
257 'Standards-Version' => { | |
258 allowed => ALL_SRC, | |
259 }, | |
260 'Status' => { | |
261 allowed => CTRL_FILE_STATUS, | |
262 separator => FIELD_SEP_SPACE, | |
263 }, | |
264 'Subarchitecture' => { | |
265 allowed => ALL_PKG, | |
266 }, | |
267 'Suggests' => { | |
268 allowed => ALL_PKG, | |
269 separator => FIELD_SEP_COMMA, | |
270 dependency => 'normal', | |
271 dep_order => 4, | |
272 }, | |
273 'Tag' => { | |
274 allowed => ALL_PKG, | |
275 separator => FIELD_SEP_COMMA, | |
276 }, | |
277 'Task' => { | |
278 allowed => ALL_PKG, | |
279 }, | |
280 'Triggers-Awaited' => { | |
281 allowed => CTRL_FILE_STATUS, | |
282 separator => FIELD_SEP_SPACE, | |
283 }, | |
284 'Triggers-Pending' => { | |
285 allowed => CTRL_FILE_STATUS, | |
286 separator => FIELD_SEP_SPACE, | |
287 }, | |
288 'Uploaders' => { | |
289 allowed => ALL_SRC, | |
290 separator => FIELD_SEP_COMMA, | |
291 }, | |
292 'Urgency' => { | |
293 allowed => ALL_CHANGES, | |
294 }, | |
295 'Vcs-Browser' => { | |
296 allowed => ALL_SRC, | |
297 }, | |
298 'Vcs-Arch' => { | |
299 allowed => ALL_SRC, | |
300 }, | |
301 'Vcs-Bzr' => { | |
302 allowed => ALL_SRC, | |
303 }, | |
304 'Vcs-Cvs' => { | |
305 allowed => ALL_SRC, | |
306 }, | |
307 'Vcs-Darcs' => { | |
308 allowed => ALL_SRC, | |
309 }, | |
310 'Vcs-Git' => { | |
311 allowed => ALL_SRC, | |
312 }, | |
313 'Vcs-Hg' => { | |
314 allowed => ALL_SRC, | |
315 }, | |
316 'Vcs-Mtn' => { | |
317 allowed => ALL_SRC, | |
318 }, | |
319 'Vcs-Svn' => { | |
320 allowed => ALL_SRC, | |
321 }, | |
322 'Vendor' => { | |
323 allowed => CTRL_FILE_VENDOR, | |
324 }, | |
325 'Vendor-Url' => { | |
326 allowed => CTRL_FILE_VENDOR, | |
327 }, | |
328 'Version' => { | |
329 allowed => (ALL_PKG | ALL_SRC | ALL_CHANGES) & | |
330 (~(CTRL_INFO_SRC | CTRL_INFO_PKG)), | |
331 }, | |
332 ); | |
333 | |
334 my @checksum_fields = map { &field_capitalize("Checksums-$_") } checksums_get_li
st(); | |
335 my @sum_fields = map { $_ eq 'md5' ? 'MD5sum' : &field_capitalize($_) } | |
336 checksums_get_list(); | |
337 &field_register($_, CTRL_PKG_SRC | CTRL_FILE_CHANGES) foreach @checksum_fields; | |
338 &field_register($_, CTRL_INDEX_PKG, | |
339 separator => FIELD_SEP_LINE | FIELD_SEP_SPACE) foreach @sum_fiel
ds; | |
340 | |
341 our %FIELD_ORDER = ( | |
342 CTRL_PKG_DEB() => [ | |
343 qw(Package Package-Type Source Version Built-Using Kernel-Version | |
344 Built-For-Profiles Architecture Subarchitecture | |
345 Installer-Menu-Item Essential Origin Bugs | |
346 Maintainer Installed-Size), &field_list_pkg_dep(), | |
347 qw(Section Priority Multi-Arch Homepage Description Tag Task) | |
348 ], | |
349 CTRL_PKG_SRC() => [ | |
350 qw(Format Source Binary Architecture Version Origin Maintainer | |
351 Uploaders Homepage Standards-Version Vcs-Browser | |
352 Vcs-Arch Vcs-Bzr Vcs-Cvs Vcs-Darcs Vcs-Git Vcs-Hg Vcs-Mtn | |
353 Vcs-Svn), &field_list_src_dep(), qw(Package-List), | |
354 @checksum_fields, qw(Files) | |
355 ], | |
356 CTRL_FILE_CHANGES() => [ | |
357 qw(Format Date Source Binary Binary-Only Built-For-Profiles Architecture | |
358 Version Distribution Urgency Maintainer Changed-By Description | |
359 Closes Changes), | |
360 @checksum_fields, qw(Files) | |
361 ], | |
362 CTRL_CHANGELOG() => [ | |
363 qw(Source Binary-Only Version Distribution Urgency Maintainer | |
364 Date Closes Changes) | |
365 ], | |
366 CTRL_FILE_STATUS() => [ # Same as fieldinfos in lib/dpkg/parse.c | |
367 qw(Package Essential Status Priority Section Installed-Size Origin | |
368 Maintainer Bugs Architecture Multi-Arch Source Version Config-Version | |
369 Replaces Provides Depends Pre-Depends Recommends Suggests Breaks | |
370 Conflicts Enhances Conffiles Description Triggers-Pending | |
371 Triggers-Awaited) | |
372 ], | |
373 ); | |
374 # Order for CTRL_INDEX_PKG is derived from CTRL_PKG_DEB | |
375 $FIELD_ORDER{CTRL_INDEX_PKG()} = [ @{$FIELD_ORDER{CTRL_PKG_DEB()}} ]; | |
376 &field_insert_before(CTRL_INDEX_PKG, 'Section', 'Filename', 'Size', @sum_fields)
; | |
377 # Order for CTRL_INDEX_SRC is derived from CTRL_PKG_SRC | |
378 $FIELD_ORDER{CTRL_INDEX_SRC()} = [ @{$FIELD_ORDER{CTRL_PKG_SRC()}} ]; | |
379 @{$FIELD_ORDER{CTRL_INDEX_SRC()}} = map { $_ eq 'Source' ? 'Package' : $_ } | |
380 @{$FIELD_ORDER{CTRL_PKG_SRC()}}; | |
381 &field_insert_after(CTRL_INDEX_SRC, 'Version', 'Priority', 'Section'); | |
382 &field_insert_before(CTRL_INDEX_SRC, 'Checksums-Md5', 'Directory'); | |
383 | |
384 =encoding utf8 | |
385 | |
386 =head1 NAME | |
387 | |
388 Dpkg::Control::FieldsCore - manage (list of official) control fields | |
389 | |
390 =head1 DESCRIPTION | |
391 | |
392 The modules contains a list of fieldnames with associated meta-data explaining | |
393 in which type of control information they are allowed. The types are the | |
394 CTRL_* constants exported by Dpkg::Control. | |
395 | |
396 =head1 FUNCTIONS | |
397 | |
398 =over 4 | |
399 | |
400 =item my $f = field_capitalize($field_name) | |
401 | |
402 Returns the field name properly capitalized. All characters are lowercase, | |
403 except the first of each word (words are separated by a hyphen in field names). | |
404 | |
405 =cut | |
406 | |
407 sub field_capitalize($) { | |
408 my $field = lc(shift); | |
409 # Some special cases due to history | |
410 return 'MD5sum' if $field eq 'md5sum'; | |
411 return uc($field) if checksums_is_supported($field); | |
412 # Generic case | |
413 return join '-', map { ucfirst } split /-/, $field; | |
414 } | |
415 | |
416 =item field_is_official($fname) | |
417 | |
418 Returns true if the field is official and known. | |
419 | |
420 =cut | |
421 | |
422 sub field_is_official($) { | |
423 return exists $FIELDS{field_capitalize($_[0])}; | |
424 } | |
425 | |
426 =item field_is_allowed_in($fname, @types) | |
427 | |
428 Returns true (1) if the field $fname is allowed in all the types listed in | |
429 the list. Note that you can use type sets instead of individual types (ex: | |
430 CTRL_FILE_CHANGES | CTRL_CHANGELOG). | |
431 | |
432 field_allowed_in(A|B, C) returns true only if the field is allowed in C | |
433 and either A or B. | |
434 | |
435 Undef is returned for non-official fields. | |
436 | |
437 =cut | |
438 | |
439 sub field_is_allowed_in($@) { | |
440 my ($field, @types) = @_; | |
441 $field = field_capitalize($field); | |
442 return unless field_is_official($field); | |
443 | |
444 return 0 if not scalar(@types); | |
445 foreach my $type (@types) { | |
446 next if $type == CTRL_UNKNOWN; # Always allowed | |
447 return 0 unless $FIELDS{$field}{allowed} & $type; | |
448 } | |
449 return 1; | |
450 } | |
451 | |
452 =item field_transfer_single($from, $to, $field) | |
453 | |
454 If appropriate, copy the value of the field named $field taken from the | |
455 $from Dpkg::Control object to the $to Dpkg::Control object. | |
456 | |
457 Official fields are copied only if the field is allowed in both types of | |
458 objects. Custom fields are treated in a specific manner. When the target | |
459 is not among CTRL_PKG_SRC, CTRL_PKG_DEB or CTRL_FILE_CHANGES, then they | |
460 are alway copied as is (the X- prefix is kept). Otherwise they are not | |
461 copied except if the target object matches the target destination encoded | |
462 in the field name. The initial X denoting custom fields can be followed by | |
463 one or more letters among "S" (Source: corresponds to CTRL_PKG_SRC), "B" | |
464 (Binary: corresponds to CTRL_PKG_DEB) or "C" (Changes: corresponds to | |
465 CTRL_FILE_CHANGES). | |
466 | |
467 Returns undef if nothing has been copied or the name of the new field | |
468 added to $to otherwise. | |
469 | |
470 =cut | |
471 | |
472 sub field_transfer_single($$;$) { | |
473 my ($from, $to, $field) = @_; | |
474 $field //= $_; | |
475 my ($from_type, $to_type) = ($from->get_type(), $to->get_type()); | |
476 $field = field_capitalize($field); | |
477 | |
478 if (field_is_allowed_in($field, $from_type, $to_type)) { | |
479 $to->{$field} = $from->{$field}; | |
480 return $field; | |
481 } elsif ($field =~ /^X([SBC]*)-/i) { | |
482 my $dest = $1; | |
483 if (($dest =~ /B/i and $to_type == CTRL_PKG_DEB) or | |
484 ($dest =~ /S/i and $to_type == CTRL_PKG_SRC) or | |
485 ($dest =~ /C/i and $to_type == CTRL_FILE_CHANGES)) | |
486 { | |
487 my $new = $field; | |
488 $new =~ s/^X([SBC]*)-//i; | |
489 $to->{$new} = $from->{$field}; | |
490 return $new; | |
491 } elsif ($to_type != CTRL_PKG_DEB and | |
492 $to_type != CTRL_PKG_SRC and | |
493 $to_type != CTRL_FILE_CHANGES) | |
494 { | |
495 $to->{$field} = $from->{$field}; | |
496 return $field; | |
497 } | |
498 } elsif (not field_is_allowed_in($field, $from_type)) { | |
499 warning(_g("unknown information field '%s' in input data in %s"), | |
500 $field, $from->get_option('name') || _g('control information')); | |
501 } | |
502 return; | |
503 } | |
504 | |
505 =item field_transfer_all($from, $to) | |
506 | |
507 Transfer all appropriate fields from $from to $to. Calls | |
508 field_transfer_single() on all fields available in $from. | |
509 | |
510 Returns the list of fields that have been added to $to. | |
511 | |
512 =cut | |
513 | |
514 sub field_transfer_all($$) { | |
515 my ($from, $to) = @_; | |
516 my (@res, $res); | |
517 foreach my $k (keys %$from) { | |
518 $res = field_transfer_single($from, $to, $k); | |
519 push @res, $res if $res and defined wantarray; | |
520 } | |
521 return @res; | |
522 } | |
523 | |
524 =item field_ordered_list($type) | |
525 | |
526 Returns an ordered list of fields for a given type of control information. | |
527 This list can be used to output the fields in a predictable order. | |
528 The list might be empty for types where the order does not matter much. | |
529 | |
530 =cut | |
531 | |
532 sub field_ordered_list($) { | |
533 my ($type) = @_; | |
534 return @{$FIELD_ORDER{$type}} if exists $FIELD_ORDER{$type}; | |
535 return (); | |
536 } | |
537 | |
538 =item field_list_src_dep() | |
539 | |
540 List of fields that contains dependencies-like information in a source | |
541 Debian package. | |
542 | |
543 =cut | |
544 | |
545 sub field_list_src_dep() { | |
546 my @list = sort { | |
547 $FIELDS{$a}{dep_order} <=> $FIELDS{$b}{dep_order} | |
548 } grep { | |
549 field_is_allowed_in($_, CTRL_PKG_SRC) and | |
550 exists $FIELDS{$_}{dependency} | |
551 } keys %FIELDS; | |
552 return @list; | |
553 } | |
554 | |
555 =item field_list_pkg_dep() | |
556 | |
557 List of fields that contains dependencies-like information in a binary | |
558 Debian package. The fields that express real dependencies are sorted from | |
559 the stronger to the weaker. | |
560 | |
561 =cut | |
562 | |
563 sub field_list_pkg_dep() { | |
564 my @keys = keys %FIELDS; | |
565 my @list = sort { | |
566 $FIELDS{$a}{dep_order} <=> $FIELDS{$b}{dep_order} | |
567 } grep { | |
568 field_is_allowed_in($_, CTRL_PKG_DEB) and | |
569 exists $FIELDS{$_}{dependency} | |
570 } @keys; | |
571 return @list; | |
572 } | |
573 | |
574 =item field_get_dep_type($field) | |
575 | |
576 Return the type of the dependency expressed by the given field. Can | |
577 either be "normal" for a real dependency field (Pre-Depends, Depends, ...) | |
578 or "union" for other relation fields sharing the same syntax (Conflicts, | |
579 Breaks, ...). Returns undef for fields which are not dependencies. | |
580 | |
581 =cut | |
582 | |
583 sub field_get_dep_type($) { | |
584 my $field = field_capitalize($_[0]); | |
585 return unless field_is_official($field); | |
586 return $FIELDS{$field}{dependency} if exists $FIELDS{$field}{dependency}; | |
587 return; | |
588 } | |
589 | |
590 =item field_get_sep_type($field) | |
591 | |
592 Return the type of the field value separator. Can be one of FIELD_SEP_UNKNOWN, | |
593 FIELD_SEP_SPACE, FIELD_SEP_COMMA or FIELD_SEP_LINE. | |
594 | |
595 =cut | |
596 | |
597 sub field_get_sep_type($) { | |
598 my $field = field_capitalize($_[0]); | |
599 | |
600 return $FIELDS{$field}{separator} if exists $FIELDS{$field}{separator}; | |
601 return FIELD_SEP_UNKNOWN; | |
602 } | |
603 | |
604 =item field_register($field, $allowed_types, %opts) | |
605 | |
606 Register a new field as being allowed in control information of specified | |
607 types. %opts is optional | |
608 | |
609 =cut | |
610 | |
611 sub field_register($$;@) { | |
612 my ($field, $types, %opts) = @_; | |
613 $field = field_capitalize($field); | |
614 $FIELDS{$field} = { | |
615 allowed => $types, | |
616 %opts | |
617 }; | |
618 } | |
619 | |
620 =item field_insert_after($type, $ref, @fields) | |
621 | |
622 Place field after another one ($ref) in output of control information of | |
623 type $type. | |
624 | |
625 =cut | |
626 sub field_insert_after($$@) { | |
627 my ($type, $field, @fields) = @_; | |
628 return 0 if not exists $FIELD_ORDER{$type}; | |
629 ($field, @fields) = map { field_capitalize($_) } ($field, @fields); | |
630 @{$FIELD_ORDER{$type}} = map { | |
631 ($_ eq $field) ? ($_, @fields) : $_ | |
632 } @{$FIELD_ORDER{$type}}; | |
633 return 1; | |
634 } | |
635 | |
636 =item field_insert_before($type, $ref, @fields) | |
637 | |
638 Place field before another one ($ref) in output of control information of | |
639 type $type. | |
640 | |
641 =cut | |
642 sub field_insert_before($$@) { | |
643 my ($type, $field, @fields) = @_; | |
644 return 0 if not exists $FIELD_ORDER{$type}; | |
645 ($field, @fields) = map { field_capitalize($_) } ($field, @fields); | |
646 @{$FIELD_ORDER{$type}} = map { | |
647 ($_ eq $field) ? (@fields, $_) : $_ | |
648 } @{$FIELD_ORDER{$type}}; | |
649 return 1; | |
650 } | |
651 | |
652 =back | |
653 | |
654 =head1 AUTHOR | |
655 | |
656 Raphaël Hertzog <hertzog@debian.org>. | |
657 | |
658 =cut | |
659 | |
660 1; | |
OLD | NEW |