1#!/usr/bin/perl
2
3#
4# Generate the AUTHORS file combining existing AUTHORS file with
5# git commit log.
6#
7# Usage: generate_authors.pl AUTHORS.src
8
9#
10# Copyright 2016 Michael Mann (see AUTHORS file)
11#
12# Wireshark - Network traffic analyzer
13# By Gerald Combs <gerald@wireshark.org>
14# Copyright 1998 Gerald Combs
15#
16# SPDX-License-Identifier: GPL-2.0-or-later
17
18use warnings;
19use strict;
20use Getopt::Long;
21use Encode qw(encode decode);
22
23my $state = "";
24my %contributors = ();
25my $is_contributing = 0;
26
27my $header = "
28
29= Original Author =
30
31Gerald Combs            <gerald[AT]wireshark.org>
32
33
34";
35
36my $trailer = "
37
38= Acknowledgements =
39
40Dan Lasley <dlasley[AT]promus.com> gave permission for his dumpit() hex-dump routine to be used.
41
42Mattia Cazzola <mattiac[AT]alinet.it> provided a patch to the hex dump display routine.
43
44We use the exception module from Kazlib, a C library written by Kaz Kylheku <kaz[AT]kylheku.com>. Thanks go to him for his well-written library. The Kazlib home page can be found at http://www.kylheku.com/~kaz/kazlib.html
45
46We use Lua BitOp, written by Mike Pall, for bitwise operations on numbers in Lua. The Lua BitOp home page can be found at https://bitop.luajit.org
47
48snax <snax[AT]shmoo.com> gave permission to use his(?) weak key detection code from Airsnort.
49
50IANA gave permission for their port-numbers file to be used.
51
52We use the natural order string comparison algorithm, written by Martin Pool <mbp[AT]sourcefrog.net>.
53
54Emanuel Eichhammer <support[AT]qcustomplot.com> granted permission to use QCustomPlot.
55
56Insecure.Com LLC (\"The Nmap Project\") has granted the Wireshark Foundation permission to distribute Npcap with our Windows installers.
57";
58
59my $git_log_text = "
60= From git log =
61
62";
63
64# Perl trim function to remove whitespace from the start and end of the string
65sub trim($)
66{
67	my $string = shift;
68	$string =~ s/^\s+//;
69	$string =~ s/\s+$//;
70	return $string;
71}
72
73sub parse_author_name {
74	my $full_name = $_[0];
75	my $email_key;
76
77	if ($full_name =~ /^([\w\.\-\'\x80-\xff]+(\s*[\w+\.\-\'\x80-\xff])*)\s+<([^>]*)>/) {
78		#Make an exception for Gerald because he's part of the header
79		if ($3 ne "gerald[AT]wireshark.org") {
80			$email_key = lc($3);
81			$contributors{$email_key} = $1;
82			print encode('UTF-8', "$full_name\n");
83		}
84	} elsif ($full_name =~ /^([\w\.\-\'\x80-\xff]+(\s*[\w+\.\-\'\x80-\xff])*)\s+\(/) {
85		$contributors{"<no_email>"} = $1;
86		print encode('UTF-8', "$full_name\n");
87	}
88}
89
90sub parse_git_name {
91	my $full_name = $_[0];
92	my $name;
93	my $email;
94	my $email_key;
95	my $len;
96	my $ntab = 3;
97	my $line;
98
99	#  4321	Navin R. Johnson <nrjohnson@example.com>
100	if ($full_name =~ /^\s*\d+\s+([^<]*)\s*<([^>]*)>/) {
101		$name = trim($1);
102		#Convert real email address to "spam proof" one
103		$email = trim($2);
104		$email =~ s/@/[AT]/g;
105		$email_key = lc($email);
106
107		if (!exists($contributors{ $email_key })) {
108			#Make an exception for Gerald because he's part of the header
109			if ($email ne "gerald[AT]wireshark.org") {
110				$len = length $name;
111				if ($len >= 8 * $ntab) {
112					$line = "$name <$email>";
113				} else {
114					$ntab -= $len / 8;
115					$ntab +=1 if ($len % 8);
116					$line = $name . "\t" x $ntab . "<$email>";
117				}
118				$contributors{$email_key} = $1;
119				print encode('UTF-8', "$line\n");
120			}
121		}
122	}
123}
124
125# ---------------------------------------------------------------------
126#
127# MAIN
128#
129
130print $header;
131
132open( my $author_fh, '<', $ARGV[0] ) or die "Can't open $ARGV[0]: $!";
133while ( my $line = decode('UTF-8', <$author_fh>) ) {
134	chomp $line;
135
136	last if ($line =~ "Acknowledgements");
137
138	if ($line =~ "Contributors") {
139		$is_contributing = 1;
140	} elsif ($is_contributing == 0) {
141		next;
142	}
143
144	if ($line =~ /([^\{]*)\{/) {
145		parse_author_name($line);
146		$state = "s_in_bracket";
147	} elsif ($state eq "s_in_bracket") {
148		if ($line =~ /([^\}]*)\}/) {
149			print encode('UTF-8', "$line\n");
150			$state = "";
151		} else {
152			print encode('UTF-8', "$line\n");
153		}
154	} elsif ($line =~ /</) {
155		parse_author_name($line);
156	} elsif ($line =~ "(e-mail address removed at contributor's request)") {
157		parse_author_name($line);
158	} else {
159		print encode('UTF-8', "$line\n");
160	}
161}
162close $author_fh;
163
164print $git_log_text;
165
166open( my $git_author_fh, 'git --no-pager shortlog -se HEAD|')
167        or die "Can't execute git shortlog: $!";
168
169while ( my $git_line = decode('UTF-8', <$git_author_fh>) ) {
170	chomp $git_line;
171
172	parse_git_name($git_line);
173}
174close $git_author_fh;
175
176print $trailer;
177
178__END__
179