XAvAX
6th June 2007, 02:45
Pretty self-explanatory, tried to comment it well. Hope it's useful!
Currently, it only converts individual entries from the old to the XML format, rather than generating a correctly formatted file. This is because I haven't been able to track down a sample "proper" KEYDB.xml file. Pointers would be appreciated. Nonetheless, it is still useful in that the output to STDOUT can be inserted into existing KEYDB.xml files, as I have set it to only output lines which conform to the pattern on STDOUT. It can also be run without arguments, and one can simply paste in an existing KEYDB.cfg line, hit enter, and get it in XML format in response.
Until I can find an example of the XML format for CPS Unit Keys and Title Keys, this program will be limited to VUK entries - However, only the format is needed, and one example of each should suffice (although a valid KEYDB.xml file is preferred for the sake of completeness).
#!/usr/bin/env perl
# This program is available under the terms of the GNU GPL version 2 or later.
# It is provided without warrantee, including that of merchantability or usefulness.
# This is a quick perl script to convert from the legacy KEYDB.cfg format to the more expressive
# XML format. It takes a list of files from the commandline, reads them line-by-line, and prints
# each line in XML format to STDOUT. Any input not understood will be printed to STDERR unchanged.
# If no files are specified, it will read from STDIN. It OUGHT to be platform-neutral, but I have only
# tested Windows (ActivePerl 5.8.8.820) and Linux (Perl 5.8.8).
use strict;
while (<>) {
chomp;
# First make sure that the line isn't a comment:
if ( $_ =~ m{^;(.*)} ) { # Match any line starting with a ";", and exclude the ; from the capturing parenthesis
warn "$_\n"; # Changed to output on STDERR untill I can see a valid KEYDB.xml file to learn how comments are done
# Then make sure that it isn't already in XML format:
} elsif ( $_ =~ m{(<.*/>)} ) { # Match any line enclosed in "<" and "/>"
print "$_\n";
# Then convert VolumeKey - based entries with origin to XML format:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*)\s+\( # Match anything for the movie title, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
V\|(.*?)\|\s # Make sure it's a VUK entry, and match the date of creation
*([\dA-F]{32}) # Match a 32-character hexadecimal value (the VUK)
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
print "<Title Description=\"$2\" Origin=\"$3\" ReleaseDate=\"$4\" hash=\"$1\" VolumeKey=\"$5\" />\n";
# Then convert VolumeKey - based entries without origin to XML format
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
V\|(.*?)\|\s* # Make sure it's a VUK entry, and match the date of creation
([\dA-F]{32}) # Match a 32-character hexadecimal value (the VUK)
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
print "<Title Description=\"$2\" ReleaseDate=\"$3\" hash=\"$1\" VolumeKey=\"$4\" />\n";
# Then convert CPS Unit Key based entries with origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\( # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
U\|(.*?)\|\s* # Make sure it's a CPS Unit Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple CPS Keys
my $cps_keys_portion = $4;
my %cps_keys_by_index;
while ( $cps_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${cps_keys_by_index{$1}} = $2; # store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for CPS Unit Key based entries, so the program will print the original string.
warn "$_\n";
# Then convert CPS Unit Key based entries without origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
U\|(.*?) # Make sure it's a CPS Unit Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple CPS Keys
my $cps_keys_portion = $4;
my %cps_keys_by_index;
while ( $cps_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${cps_keys_by_index{$1}} = $2; # store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for CPS Unit Key based entries, so the program will print the original string.
warn "$_\n";
# Finally, convert Title Key based entries with origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\( # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
T\|(.*?)\|\s* # Make sure it's a Title Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple Title Keys
my $title_keys_portion = $4;
my %title_keys_by_index;
while ( $title_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${title_keys_by_index{$1}} = $2;# store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for Title Key based entries, so the program will print the original string.
warn "$_\n";
# Finally, convert Title Key based entries without origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
T\|(.*?) # Make sure it's a Title Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple Title Keys
my $title_keys_portion = $4;
my %title_keys_by_index;
while ( $title_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${title_keys_by_index{$1}} = $2;# store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for Title Key based entries, so the program will print the original string.
warn "$_\n";
# If it doesn't match any of these, it's probably a movie title with parentheses in it but no origin, or misformatted.
# These will have to be done manually, so I'll print them unmodified
} else {
warn "$_\n";
}
}
print "\n";
Edits 1 - 10 occurred while this script was in its previous location in the HD-DVD Keys Sticky.
Edit 1: Fixed it to make it case-insensitive (for keys, hashes, and (T|U|V))
Edit 2: Fixed it to append a trailing newline for compatibility
Edit 3: Commented the regexes & added semi-graceful handling of in-title parentheses
Edit 4: My comments seem to have made it break, reverting. Also tested it, now tested to work with ActivePerl 5.8.8.820 on Windows (used the post below mine to test)
Edit 5: Fixed it appending newlines to every line, realized that KEYDB.cfg comments are denoted by a semicolon (no difference in output there, but hey, I'm OCD), and made the match regexes explicit with m/. Also tidied up case-insensitivity with /i. Ack, I just realized that the entries checking for Title keys looked for a |U| instead of a |T| - It didn't affect the output, but it was incorrect. Fixed. Additionally, tested on Gentoo Linux with Perl 5.8.8.
Edit 6: Added semicolons after commands. Not strictly necessary, as all of them are at the ends of blocks, but if commands are added later this will keep it from breaking.
Edit 7: Made it so that, if it gets something it doesn't understand, it sends it to STDERR instead of STDOUT. This makes it possible to output all the properly XML-formatted stuff to one place and all the other stuff somewhere else. In any Bourne-compatible shell, STDOUT can be redirected with 1> or 1>>, and STDERR with 2> or 2>>. I am unsure of how Windows handles STDERR, and plan to test it later today.
Edit 8: Modified regexes to verify that hashes and keys are the proper length (40 characters and 32 characters, respectively)
Edit 9: Used non-standard regex delimiters (curly brackets) to eliminate the necessity of escaping slashes - being a directional character, internal curly brackets will scope themselves to within the regex, and will only fail if unpaired (in which case they would fail anyway)
Edit 10: Added proper regex comments with the /x modifier and enabled true (CPS Unit|Title) Key processing
:helpful:
Currently, it only converts individual entries from the old to the XML format, rather than generating a correctly formatted file. This is because I haven't been able to track down a sample "proper" KEYDB.xml file. Pointers would be appreciated. Nonetheless, it is still useful in that the output to STDOUT can be inserted into existing KEYDB.xml files, as I have set it to only output lines which conform to the pattern on STDOUT. It can also be run without arguments, and one can simply paste in an existing KEYDB.cfg line, hit enter, and get it in XML format in response.
Until I can find an example of the XML format for CPS Unit Keys and Title Keys, this program will be limited to VUK entries - However, only the format is needed, and one example of each should suffice (although a valid KEYDB.xml file is preferred for the sake of completeness).
#!/usr/bin/env perl
# This program is available under the terms of the GNU GPL version 2 or later.
# It is provided without warrantee, including that of merchantability or usefulness.
# This is a quick perl script to convert from the legacy KEYDB.cfg format to the more expressive
# XML format. It takes a list of files from the commandline, reads them line-by-line, and prints
# each line in XML format to STDOUT. Any input not understood will be printed to STDERR unchanged.
# If no files are specified, it will read from STDIN. It OUGHT to be platform-neutral, but I have only
# tested Windows (ActivePerl 5.8.8.820) and Linux (Perl 5.8.8).
use strict;
while (<>) {
chomp;
# First make sure that the line isn't a comment:
if ( $_ =~ m{^;(.*)} ) { # Match any line starting with a ";", and exclude the ; from the capturing parenthesis
warn "$_\n"; # Changed to output on STDERR untill I can see a valid KEYDB.xml file to learn how comments are done
# Then make sure that it isn't already in XML format:
} elsif ( $_ =~ m{(<.*/>)} ) { # Match any line enclosed in "<" and "/>"
print "$_\n";
# Then convert VolumeKey - based entries with origin to XML format:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*)\s+\( # Match anything for the movie title, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
V\|(.*?)\|\s # Make sure it's a VUK entry, and match the date of creation
*([\dA-F]{32}) # Match a 32-character hexadecimal value (the VUK)
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
print "<Title Description=\"$2\" Origin=\"$3\" ReleaseDate=\"$4\" hash=\"$1\" VolumeKey=\"$5\" />\n";
# Then convert VolumeKey - based entries without origin to XML format
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
V\|(.*?)\|\s* # Make sure it's a VUK entry, and match the date of creation
([\dA-F]{32}) # Match a 32-character hexadecimal value (the VUK)
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
print "<Title Description=\"$2\" ReleaseDate=\"$3\" hash=\"$1\" VolumeKey=\"$4\" />\n";
# Then convert CPS Unit Key based entries with origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\( # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
U\|(.*?)\|\s* # Make sure it's a CPS Unit Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple CPS Keys
my $cps_keys_portion = $4;
my %cps_keys_by_index;
while ( $cps_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${cps_keys_by_index{$1}} = $2; # store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for CPS Unit Key based entries, so the program will print the original string.
warn "$_\n";
# Then convert CPS Unit Key based entries without origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
U\|(.*?) # Make sure it's a CPS Unit Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple CPS Keys
my $cps_keys_portion = $4;
my %cps_keys_by_index;
while ( $cps_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${cps_keys_by_index{$1}} = $2; # store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for CPS Unit Key based entries, so the program will print the original string.
warn "$_\n";
# Finally, convert Title Key based entries with origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\( # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "("
(.*?)\)\s*\| # Match the origin, and permit arbitrary whitespace until a "|"
T\|(.*?)\|\s* # Make sure it's a Title Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple Title Keys
my $title_keys_portion = $4;
my %title_keys_by_index;
while ( $title_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${title_keys_by_index{$1}} = $2;# store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for Title Key based entries, so the program will print the original string.
warn "$_\n";
# Finally, convert Title Key based entries without origin:
} elsif ( $_ =~ m{([\dA-F]{40}) # Match a 40-character hexadecimal value (the hash)
=(.*?)\s+\| # Match anything for the movie title non-greedily, stopping on whitespace that is immediately followed by a "|"
T\|(.*?) # Make sure it's a Title Key entry, and match the date of creation
(\|.*) # Match a literal "|" and anything after that - the iteration portion takes over here
}ix ) { # The /i modifier renders it case insensitive, the /x modifier permits whitespace-formatting and #Comments
# This is a section that is intended to iterate through the keys section, one "|"-enclosed piece at a time, in order to process multiple Title Keys
my $title_keys_portion = $4;
my %title_keys_by_index;
while ( $title_keys_portion =~ s{^\|\s*(\d+)\s*-\s*([\dA-F]{32})\s*}{}i ) { # This is deceptive. It's primary purpose is to match the first key and
${title_keys_by_index{$1}} = $2;# store keys in a hash # index it comes across, but its secondary intent is to set up the next
} # by removing the one that has already been seen
# I do not know the XML format for Title Key based entries, so the program will print the original string.
warn "$_\n";
# If it doesn't match any of these, it's probably a movie title with parentheses in it but no origin, or misformatted.
# These will have to be done manually, so I'll print them unmodified
} else {
warn "$_\n";
}
}
print "\n";
Edits 1 - 10 occurred while this script was in its previous location in the HD-DVD Keys Sticky.
Edit 1: Fixed it to make it case-insensitive (for keys, hashes, and (T|U|V))
Edit 2: Fixed it to append a trailing newline for compatibility
Edit 3: Commented the regexes & added semi-graceful handling of in-title parentheses
Edit 4: My comments seem to have made it break, reverting. Also tested it, now tested to work with ActivePerl 5.8.8.820 on Windows (used the post below mine to test)
Edit 5: Fixed it appending newlines to every line, realized that KEYDB.cfg comments are denoted by a semicolon (no difference in output there, but hey, I'm OCD), and made the match regexes explicit with m/. Also tidied up case-insensitivity with /i. Ack, I just realized that the entries checking for Title keys looked for a |U| instead of a |T| - It didn't affect the output, but it was incorrect. Fixed. Additionally, tested on Gentoo Linux with Perl 5.8.8.
Edit 6: Added semicolons after commands. Not strictly necessary, as all of them are at the ends of blocks, but if commands are added later this will keep it from breaking.
Edit 7: Made it so that, if it gets something it doesn't understand, it sends it to STDERR instead of STDOUT. This makes it possible to output all the properly XML-formatted stuff to one place and all the other stuff somewhere else. In any Bourne-compatible shell, STDOUT can be redirected with 1> or 1>>, and STDERR with 2> or 2>>. I am unsure of how Windows handles STDERR, and plan to test it later today.
Edit 8: Modified regexes to verify that hashes and keys are the proper length (40 characters and 32 characters, respectively)
Edit 9: Used non-standard regex delimiters (curly brackets) to eliminate the necessity of escaping slashes - being a directional character, internal curly brackets will scope themselves to within the regex, and will only fail if unpaired (in which case they would fail anyway)
Edit 10: Added proper regex comments with the /x modifier and enabled true (CPS Unit|Title) Key processing
:helpful: