#! /bin/sh ## Copyright (C) 2000-2005 Francesco Potort́ ## Made on September 2000 by Francesco Potort́ ## current version is 1.49 ## This program is released under the GNU GPL, whichever version, ## which is available at http://www.gnu.org/licenses/gpl.txt ## ## Presentation and pointer to the latest release available at ## . ## Please write to me if you want announcement of new releases. ## ## This script requires Posix compliant sh, tr and grep. ## ## TODO: ## - The `tail -1' in the code makes checkiso use only the last of a ## number of signatures with the same key in the database. Instead, ## all should be considered to allow for different disks with the same ## volume id. ## - mkisofs normally appends zero padding at the end of file systems; ## for some reason, recent versions of Nero write garbage instead on ## the last 4096 bytes; this is legal, I suppose, because that's ## padding, but it breaks checkiso. In the short term, we can add an ## option to ignore the trailing garbage (-I --ignore-garbage=2). ## Eventually, we should ignore everything after the end of the ## ISO file system, but don't know of any way to know its lenght. ## - Write a test suite to check all combinations of options; with bash ## and ash; with 0, 1 or more file names; with a database whose name ## embeds spaces; with file names embedding spaces. ## ################################################################ progname=$(basename "$0") # this program's name internal_db=$(which "$0") # the internal database of signatures version='1.49' # this program's version cdversion='3.1.0' # last Debian CD version known debsums=MD5SUMS # names of Debian MD5 hash files sumsfiles="$debsums *.md5sum" # names of MD5 hash files bsk=2 # block size for reading in KB key='#Id-' # start of a signature tmpfile=/dev/null # no temporary file generate= # flag: generate signatures, don't check notemp= # flag: never write to the disk quiet= # flag: do not emit normal messages sigfiles= # list of files containing signatures ################################################################ LC_ALL=C # make programs behave predictably ################################################################ # Parse the options arg= while : forever ; do if [ -z "$arg" ]; then # if nothing left in arg arg=$1 # examine first positional arg # if arg is not empty, not a single dash and begins with a dash if [ -n "$arg" -a "$arg" != "-" -a "${arg#?}" = "${arg#-}" ]; then shift # consume it: it is an option arg=${arg#-} # remove the dash else # not an option break # end of option parsing fi fi if [ "${arg#?}" = "${arg#-}" ]; then # if long option option=-$arg # this is the option arg= # nothing left else tail=${arg#?} # arg minus the first option option=-${arg%$tail} # the first option arg=$tail # the rest of the options fi case $option in --) # end of options break ;; -g|--generate) # generate signatures generate=yes ;; -n|--notemp) # do not write anything to the disk notemp=yes ;; -q|--quiet) # be quiet quiet=yes ;; -s|--sig-file=*) # signatures file if [ $option = -s ]; then # short option case optarg=$1; shift else # long option case optarg=${option#--sig-file=} fi sigfiles="$sigfiles '$optarg'" ;; -v|--cdversion) # last Debian version known echo $cdversion; exit 0 ;; -V|--version) # this script's version number cat <&2 <&2 exit 1 fi done test $generate && options="$options --generate" test $notemp && options="$options --notemp" test $quiet && options="$options --quiet" ################################################################ ################################################################ # We have some work to do: do some checks and parse the arguments # check whether a given executable is in the path executable_in_path () { local ex IFS ex="$1" IFS=: set -- $PATH for dir; do if [ -f "$dir/$ex" -a -x "$dir/$ex" ]; then return 0 fi done return 1 } if ! executable_in_path md5sum; then echo "$progname: cannot find the md5sum program; exiting" >&2 exit 11 fi # Check that $iso is a readable file whose Volume ID is readable, # and put that ID in $name check_iso () { if [ ! -r "$iso" ]; then return 1 # not readable fi id=$(dd if="$iso" bs=1 skip=32808 count=32 2>/dev/null) if [ $(expr length "$id") -ne 32 ]; then return 2 # Volume ID unreadable fi name=\"$(echo $id)\" return 0 # success } case $# in 0) # no arguments: look for cdroms cd= # list of readable CD drives # First, look in /dev/cdroms if ls /dev/cdroms >/dev/null 2>&1; then # okay, all of them are here, if any for iso in /dev/cdroms/*; do check_iso && cd="$cd $iso" done else # pre 2.4 kernel # look for IDE cdroms first... if ls /proc/ide/*/media >/dev/null 2>&1; then for i in /proc/ide/*/media; do if [ "$(cat $i)" = "cdrom" ]; then iso=/dev/$(basename $(dirname $i)) check_iso && cd="$cd $iso" fi done fi # ...and then add the SCSI cdroms if fgrep CD-ROM /proc/scsi/scsi >/dev/null 2>&1; then for iso in /dev/scd*; do check_iso && cd="$cd $iso" done fi fi if [ "$cd" ]; then eval exec "$0" $options $cd # got them exit # should not get here fi # Last resort iso=/dev/cdrom # the standard place if ! check_iso; then echo "Cannot read Volume ID from any CD drives" >&2 exit 1 fi ;; 1) # the image file or device iso="$1" if ! check_iso; then echo "Cannot read Volume ID from $iso" >&2 exit 1 fi ;; *) # more than one file: recursive call exitcode=0 for arg; do "$0" $options "$arg" ec=$? test $ec -gt $exitcode && exitcode=$ec && test $quiet && break done exit $exitcode esac set -- "$sigfiles" if test $generate && # generate, do not check test $# != 1 # not a single file name then echo "Only one signature file allowed with --generate" >&2 exit 10 fi # Possibly eject the CD and possibly remove temp file on exit if [ -b "$iso" ] && executable_in_path eject; then trap 'test $tmpfile = /dev/null || rm -f $tmpfile; eject $iso' 0 else trap 'test $tmpfile = /dev/null || rm -f $tmpfile' 0 fi ################################################################ ################################################################ ## Now we have a single image or CD to deal with # Create an empty temporary file. Use mktemp if it is there, else try # with $TMPDIR and $TMP make_tempfile () { if [ -z "$TMPDIR" ]; then if [ -z "$TMP" ]; then TMPDIR=/tmp else TMPDIR=$TMP fi fi executable_in_path mktemp && tmpfile=$(mktemp -q $TMPDIR/checkiso.XXXXXX) || tmpfile=/tmp/checkiso.$$ # temporary file for stderr from dd } # Read from file $iso using dd with a block size of $bsk KB. # The number of blocks read is $len, if set, else until EOF. # The stdout of dd is fed to md5sum, and the result is put in $hash. # Unless $notemp is set, the number of blocks read is put in $rlen. # If the number of blocks read cannot be parsed, return with an error. read_using_dd () { local len=$len # set from outer one and overwritten if [ -z "$notemp" ]; then # we can write to the disc make_tempfile # sets tmpfile and the trap to remove it else tmpfile=/dev/null # do not create a temporary file fi if [ -z "$len" ]; then # unknown length len=$((2000000000/$bsk)) # allow for 2TB discs fi set -- $(dd if="$iso" bs=${bsk}k count=$len 2>$tmpfile | md5sum) hash=$1 # generated by md5sum rlen= # this means lenght not computed if [ -z "$notemp" ]; then # we can write to the disc set -- $(fgrep ' records out' $tmpfile) # discard everything else rlen=$1 # rlen is "NN+x", with x 0 or 1 # Do a sanity check on $rlen to avoid unforeseen dd error # messages, and return an error if cannot parse it expr $rlen : '[0-9][0-9+]*$' >/dev/null || return 1 rlen=$(($rlen)) # set it to a number fi # length computed return 0 } ################################################################ ################################################################ ## Generate signatures if [ "$generate" ]; then if [ -n "$notemp" -a -b "$iso" ]; then echo "--generate and --notemp incompatible when reading from a CD" >&2 exit 1 fi sigfiles=$(eval echo $sigfiles) test $sigfiles && exec >> "$sigfiles" # write on file, not on stdout test $quiet || echo -n Creating signature for $name... >&2 if [ -b "$iso" ]; then # don't know the image size in advance read_using_dd # sets the hash and rlen variables else # it is a file, no need to use dd set -- $(md5sum "$iso") hash=$1 # generated by md5sum set -- $(ls -l "$iso") # get the image length rlen=$((($5+$bsk*1024-1)/1024/$bsk)) fi if [ $? = 0 ] && # read_using_dd succeeded # also do some sanity checks on $hash to avoid unforeseen error messages expr $hash : '[0-9a-zA-Z]*$' >/dev/null && [ $(expr $hash : '.*') = 32 ] then test $quiet || echo " done." >&2 echo $key $rlen $hash "<$id>" exit 0 else test $quiet || cat >&2 <" EOFfailed exit 2 fi fi ################################################################ ################################################################ ## Check image test $quiet && exec >&- # if quiet, close stdout echo "Volume ID of \`$iso' is $name" ################################################################ # Look for signature files. for f in $(for s in $sumsfiles; do echo ../$s $s; done) \ $(echo $MD5SUMS | tr : ' ') \ $internal_db; do test -f $f -a -r $f && sigfiles="$sigfiles $f" done set -- $(eval cat $sigfiles | fgrep "<$id>" | grep "^$key" | head -1) comment=$1 len=$2 sum=$3 if [ "$comment" != "$key" ]; then echo -n "I do not have a signature for this" test -b "$iso" && echo -n " disc" || echo -n " image" out=$(eval cat $sigfiles | grep '^[0-9a-f]\{32\} [-_.a-zA-Z0-9]\+\.iso$') if [ "$out" ]; then echo ", trying the sums in MD5 sum files." len= # not significant sum=x # an invalid sum else if [ "$id" != "${id%Debian*}" ]; then # if the word "Debian" is there echo ", and I cannot find any $debsums file." else # nothing to do with Debian echo "." # do not speak about MD5SUMS fi exit 2 # no signatures nor sums for this disc fi fi ################################################################ # Compute the size, if possible, and the hash. echo -n "Checking MD5 hash..." if [ -b "$iso" ]; then # reading from a device if ! read_using_dd; then # sets the hash and rlen variables echo " FAILED!" # error from dd exit 3 fi else # reading from a file set -- $(ls -l "$iso") # get the image length rlen=$((($5+$bsk*1024-1)/1024/$bsk)) fi # Do this check only if we have a regular signature for this disc # and if we could get the length of the disc if [ $sum != x ] && [ -n "$rlen" -a $rlen -ne $len ]; then echo " FAILED! ($rlen/$len sectors read)" exit 3 fi if [ ! -b "$iso" ]; then # reading from a file set -- $(md5sum "$iso") # don't need dd hash=$1 # generated by md5sum fi ################################################################ # We have a hash. if [ $sum != x ]; then if [ "$hash" = $sum ]; then echo " success" exit 0 fi echo " FAILED! ($rlen/$len sectors read, but MD5 hash does not match)" exit 3 fi set -- $out while [ $1 ]; do sum=$1 file=$2 shift 2 if [ "$hash" = $sum ]; then echo " matches \`$file'" exit 0 fi done echo " FAILED! ($rlen sectors read, no signature, and no matching MD5 sum)" exit 3 ################################################################ ################################################################ ## Internal signatures database. Format is: ## #Id- blocks 256-bit MD5 sum ## ## #Id- 312412 c2c046ed739d78d56b1c5b34202268d1 #Id- 265072 f126f97fb20f3e1dd4868ae1d3309d24 #Id- 303863 cfe9668229ff8310b7f6b8feb3caeeb8 #Id- 287573 9d9327e8f724601ecfcce282f51d2c77 #Id- 319280 acc48762d94a677fcd9f30d49ab8e6d1 #Id- 325760 5cd9fe3a04e547121f28e3993cffbae2 #Id- 326208 2d9bf34d171d72a19de5208bc59c7ee0 #Id- 226880 c142924582341273b4e546a67da2a3de #Id- 325744 ba15957ea6d45e68e95bbf8c399d5e32 #Id- 330160 84242ace11f0a4fe38291c8bf36bb67c #Id- 325392 85bc3988b02743bd8999db6730b4f2d4 #Id- 14336 b1594c75686377210ae931df1544fe28 #Id- 326720 d982f6485dc1b039789a78ad4548749d #Id- 332480 ca3e0e4f124dfa8d12e8cd491402e68c #Id- 326816 47b2f4da36366added5d8ffebb9c62b9 #Id- 239248 6f669c80d6a7fea1b082817d4cc58c34 #Id- 323472 32aab39139f2ae3ed7d6faedf127b7c6 #Id- 330432 0b58108651faabbdf190fda8baf87fde #Id- 329232 7ff511a20c02a2f8d9c1a2c171a97198 #Id- 100320 51968efc81716cb673ae33464d3481bd #Id- 325200 401a78203975458dd20e93dbbb60851b #Id- 331664 3a1756eca42f30f12ce15667b80ef33a #Id- 314624 15abbbcc01bd26cf598b3b2e130dc334 #Id- 123488 3e4ab64fbdff01c993eff5d38eb9ab0b #Id- 314992 9add05140d2c013723f6d04a2c69583c #Id- 326512 bc98c4c77a2324cd538eda7c33d2a7b0 #Id- 327824 e10538650487fb66d2fae1e227c77843 #Id- 283168 8f3fa2cf29ecaac8d365748cc00bedc5 #Id- 322736 387c22605764cfc1ce8bf34157ad5d66 #Id- 328656 2c83855610df561bf302185fe9f94004 #Id- 325184 e53964a152aab38ec7a8a467af31218e #Id- 146064 4863bc8a1dd22e7a018111e6f82611bb #Id- 295041 d84bfb2af9060e59c1795adb9284738e #Id- 324986 0c5f926b0e0e5f6a086dbfe933fada25 #Id- 326295 5212d0e63690f2d867a6c75cd20997ec #Id- 327500 245c518d4bcdd59790f011a651fb7443 #Id- 325763 152c188e42af2e700019d8d5e8412df3 #Id- 319224 0e1469ff2eb4d7ccec7c219045351a49 #Id- 325671 7973df14be596a48d4325914a59a3033 #Id- 86672 0a16967e10d723d5a50d5bee97c0103c #Id- 318789 4440a8e15c9f40803122cec599f74ff3 #Id- 142084 f4981ebc5a524587b5d0d32d63507457 #Id- 296004 1e28f6bd054cd04387be0db1a5a7ece1 #Id- 329190 aef9273aa15cc23cc414beb6ea4f331b #Id- 309187 26fa7dc072dcfbd9bd32319f5cac7ea5 #Id- 309578 a386f771806313687961c658d98927ac #Id- 305277 8deca9238495393d65859b76e921d627 #Id- 304138 9ca6af3e8186b3a6b2c0231a586073d4 #Id- 275189 62a8f909e2d2362d4832270dc5897473 #Id- 319163 76bd0e323f76f3758c7a8e3f41bac3d6 #Id- 113219 aef1813f11e94ab4d0bf0fa8a67f5f91 #Id- 288535 b7d1f7fbcd930c88f72562ef1239d04f #Id- 323489 22d5bf00c4e26eee411e1801053f9762 #Id- 326323 559b2f4d320923f20815c835293cedec #Id- 326198 a6580f1020386b79b720a1f93e51b435 #Id- 322323 2f70c223899d8c3db72ac9aa1d8aefe4 #Id- 324469 50656f4f1010de8be216e9e1c401d4cf #Id- 214242 3d0c01fe013468becb36a6e351ce5d8f #Id- 319219 03f3d6632949018931fd2d839c2dcdc6 #Id- 112800 d07ea28873e19ef551ea0f3e2a72eda6 #Id- 292889 f3991d6800a11a829d53015a954211e5 #Id- 325100 4e036a1f53113b95766bcfbcca7c63c5 #Id- 330156 d8ff478512dfc932abf34d18e13b4dc0 #Id- 330570 17d4642d8a5d12d9547c8d5bc887dc27 #Id- 330469 cb2e37cf1d394b24bd40f47d93dde3db #Id- 329676 f802817214758c3daf2b5804aa751dd6 #Id- 330278 29f42e84a6e44aa8590b0888165aacc6 #Id- 182994 e68a34f6e5c6b7c366f20426dec7b3d6 #Id- 318324 b5540403a160ac67b5e5be1110736915 #Id- 117055 cebcce6aa6a0e18d86f73bbdd3929391 #Id- 299899 f12b5b678d01390904e1f325f4c602c1 #Id- 331868 9917ee029c5a00cd41809fe1464bea57 #Id- 327821 e9f29e7eb7f38a345304b53b12addd51 #Id- 329577 daf9cfb77e77f7d8878ead2a448381d7 #Id- 327555 e9cc32ad02e94ab39cd468e06f57329f #Id- 315464 3522ff9158c034bf2e12aa24cf94ff80 #Id- 328763 4a55545f6c48623b80d023d82793b924 #Id- 122700 c10d4a88c1af50575680a0dda3c26dee #Id- 319041 e610fe587b8489ce5fc74c3216f151a9 #Id- 173102 e4b9bb9e1e9b352bf5ce017e036abaf5 #Id- 287440 2d1cd7559b798ea76e21ace0db766191 #Id- 323120 a8ee54e203a57d3771b2e22fe92d1dc1 #Id- 320185 7de6b3e7fe2ebd81dc6919b3d6911d1d #Id- 321915 e5e6129b25fc2cbeaea462b17eeda524 #Id- 313735 33dfad0d128fc9fe5993eb0014fb38b9 #Id- 313025 01d18fb2ec16c2dda05240133ddc08cc #Id- 294295 02b779829704e84020964282bbef717e #Id- 321937 fd6a97fabc28e418adb09ea4cec710f0 #Id- 90032 c993a5f9a97aa256511f5b74910945eb #Id- 298786 0cf1446bbb92a27206a86101b7c6a92e #Id- 326356 83cbf4dc9e03cd165e766250843151f5 #Id- 309253 cc9cc7ecb1c93bcf41ce7fc097f78518 #Id- 308860 6311ddcf16ba227cf071f21273a16bbf #Id- 303747 a7258e22e0eb2ccbe45236fa225438f8 #Id- 307547 ee4ddd138f83bfb81e93010804d7cf64 #Id- 208194 6cd54f50a1ece6b6e3be3952cfffe103 #Id- 318363 fb348a0b9dc4b92d6b6f31edc5c184b1 #Id- 99218 378739b1741a4dcf1aec86b1a11a5260 #Id- 298878 23d8d80b887dcaa95cad29ab84535bf5 #Id- 326002 122e8f30754c0cadf538178b635e3afd #Id- 320984 22b92876a26150a17fe93a218929c22d #Id- 326000 d0932ec15389b0af576ad02ff8d79e58 #Id- 323113 644a2fdc348bd23c99c0d5b18da53b09 #Id- 317914 855306d34ebe501b6a21a8c81d91c7da #Id- 150864 b9d00d4e79f5c1e0968dafac1267652b #Id- 318948 a6f714dfbdfd1e3b1935967e11c11f3b #Id- 93289 f4294eb958d461ace8ccc2c456f6e0e5 #Id- 286445 edb3e413620f2e35516cff373d4da81a #Id- 321115 fbfdcadfe92b5ab1228d1cd02e62b510 #Id- 325646 561393257b7fe125aba07db92be0f223 #Id- 322934 68ae532b42bff29a4f6cfc12b812fe8b #Id- 324428 e14cf07865d8f81604bb7d14f69ce51c #Id- 316129 3ac7c13aed242b96c7c8bdc8e7ba9036 #Id- 325350 1fbce7f72bcba875b5e14961ccf3f587 #Id- 42210 d43648f73fe52f4336b19a754d790e3c #Id- 318810 f2ef49a26eb1b11ad585e33f726f21c3 #Id- 139950 318bda6c7e46ca1e84877d761a815c84 #Id- 296263 40afc80d317925d9d7302dd8bd9b2f27 #Id- 328457 5efa04efe890fbafc427671373479c74 #Id- 310805 d84b9d81a638efc2c9cf48f26cbe032f #Id- 311061 333b9b0538b07592309dbd70cc44ea66 #Id- 308561 5215762da0b6c29fd4f54bda261bbf26 #Id- 306323 491a730aee7d850b07ad6e4443cade07 #Id- 271917 2f2377fe9c4f2395aa434dff9bbf6d74 #Id- 322417 77cfe5f68fc6e4cfec03609be6196d68 #Id- 93643 60e9124b940030588cc2a1a1eaf14f13 #Id- 291900 80cf447dbb422abc0ee75d4203914374 #Id- 330055 a16204a222a81a45f1fca648d4245f85 #Id- 327247 ce8bdc9b95473e1adca8e165d2b32a8e #Id- 331268 64d8ecb7e5092a9096246034cb884298 #Id- 331988 45d4119fd6a8e84b1aef226072ace6a7 #Id- 331668 98f41f51e097baa185050026f6ec199b #Id- 330400 b07d7827aeb08f7047c1eb3e463b02ec #Id- 269610 dbbdedf767d7c78fc597e6f633ce5b73 #Id- 168626 b0b1b9170e54a69b356617358780bd52 #Id- 289536 7c1e4e76295266ec64d130aab9bbadf1 #Id- 322320 10289d2b2671f21223cc0ba97404759d #Id- 325744 14a09ee45d957e2ad95b130c4adff7cd #Id- 324736 12c60a9f17f13610b20de1ede5340a00 #Id- 324544 d6c373bed8596fc6f7c03bc12b065be0 #Id- 323120 b922882195f05f0d14e0e533b9222747 #Id- 268336 549add87ccf82e4fd385a276403cff50 #Id- 318578 8bc737c2b18499b8ed8b6864f0fbade2 #Id- 123379 95d865da8d8819e6e2c821c91528cd4b #Id- 328414 9d67f7480eec234f8987e190ec57461d #Id- 325949 9c72442a3d9e058d03725fedfff08810 #Id- 323529 87c5ca7ea5278fb8fbb23ab971c47a3a #Id- 330158 a65534051b0077d521540d76986fb321 #Id- 328250 538d9f75a888fa4e106282e9eb9cdf46 #Id- 102323 3384930cdb8beff04acd7255387d9733 #Id- 327324 f767df2047837f858dfa0e220f09be0e #Id- 327965 8e2c120b8ea9781dee53175a80a251af #Id- 324776 dea13fbc042ad3476880d69df889f09d #Id- 326586 5ad329cb7ac18cd22ab32120321b1514 #Id- 329658 f87678d86eb60e50287d48e106a17376 #Id- 330127 d903672eadc2713430012c903c312945 #Id- 329521 e89dad53845d0f891be610c222db8f3a #Id- 329705 4b4b7045fd2d63e431f6c7f3b2e2ba15 #Id- 10988 b8729b12258a8aa59dc21471b8c4d221 #Id- 73830 aa30641fbdfc0f02bc14b30437e5a25e #Id- 310390 561ed343724775fb19abe6aa089501c1 #Id- 330576 3f4c08e9ad9de43f8ebff0f662713280 #Id- 318792 efe850d33e834ccaee4240171422d63c #Id- 328876 4450cf3f10abb1bbb715dce93abc5f55 #Id- 35203 11dbbc66d9003d3ed161ee9b410920bf #Id- 326916 e352d047d0c6862950153df365812bc0 #Id- 329439 630642df0f8ea2200366e15dae0a542d #Id- 330187 b1972613f416cfd97554140637390d42 #Id- 328294 87a601cab72936958a1b41f808fabd39 #Id- 329805 0c96d5de4f982522032ffdb394c6ce4c #Id- 330767 606c1bb17ec7ced7907a14492fa26094 #Id- 330098 e820c8aaa4bd5a8b451d97f421f2f7a2 #Id- 330329 501f2531e5c306fbffb5a632e8724790 #Id- 11550 e8c3bcef9f03c8729296763209bf601b #Id- 44048 c64638e16d86d35adf223b44652fcf0c #Id- 326711 cc85ce4a0650777fa1748b570f3fa026 #Id- 325626 fe724c493b12768f081c61b418a4ed40 #Id- 323816 05f4b97f754b3e68c43fa76abd2eee05 #Id- 316967 39e01481a0003a8b0197a7c5845d7fdc #Id- 322715 a16e9003e3a84dfa620dcdc047665b5d #Id- 69900 6d38c929e898548207d3a5c71a6e6e5a #Id- 326816 be72af243875dfc6b8bd69ebb2d4c8ef #Id- 323953 d00214a384cbb41b45092d706d9e6219 #Id- 328291 eb54f26748c6dde41d6007455acf440d #Id- 325780 a1c7df14664f2fd78be13b8ee70e06a5 #Id- 327659 dd5033280d810fd4d4c61195f6248431 #Id- 328468 5c2bf57e591ca35535215d4272b722c8 #Id- 324131 0f2889e86be77157de670e7dd1ad3256 #Id- 328662 39ad3f3076b690a85b96f831a6a136b3 #Id- 17973 931c9e265cec000004536cd4f2446ba1 #Id- 77049 a33fa443215a1d5f3ac31af46a886e80 #Id- 323025 ead6491725a464143ce2f95d2fb7f034 #Id- 329950 05eb35529d81e208f2e96690545533cf #Id- 329390 895e9691412c1a38e633a1c736fd42a5 #Id- 330953 86999afcc724cf1dbcd9ae60d2e204cf #Id- 329730 379d75ad4d40e0207ae739d019b9a618 #Id- 191150 3e0e168e5ae447b8c8a7823d44ca855c #Id- 327995 17b479f7e110dcd7b6a5042faf53e391 #Id- 319858 560c83beead679478a08dc290aabab6c #Id- 327369 8b26b3756768bc9738e1e3be3c6e8bc7 #Id- 326046 68351ef6b626312a3d6cd99f0cf5b174 #Id- 328948 fee446abbf3726ef0bcabf4758ba2c1d #Id- 327561 318f7145990147e29017ab1ae1579a0e #Id- 331073 c18ffd6124c5d8ad6d197a2614712de6 #Id- 326963 9768dd2aaf106de35833932ed0bb2f15 #Id- 15654 e81623d7e38be798f622ceb5818e44d7 #Id- 53981 7c10e124c3f257419032453c683b8d6e #Id- 325310 e4bb336d88bb7815b5ef2639467a26f1 #Id- 329892 f69ec983d8cb801c02d69c71ea1e7d5d #Id- 322986 669a81dba72de09cf9c2d604d14c17a6 #Id- 329535 acff876c3c00d09047cffffd4144831d #Id- 329044 276dddabcd63c55a57b35fc88a28e2b1 #Id- 328233 807e9876a526ad9ec5c36c63df08753f #Id- 36547 ccf14c11f1ba71844e794249b2808c0e #Id- 326662 52b7e0354074dda5be6ae92c81b882ac #Id- 326039 c8a4864792806dc7144625a262d5372b #Id- 329239 1783268867405422f92ef06d651992e0 #Id- 320533 a5bd0948bcb4309ffd2b4c7f048df768 #Id- 326153 d24a5eed2b5fbfefc28090a499fe0b15 #Id- 329088 9890403593fd2887987c5913d0b387fc #Id- 330051 9cc44fc9cbd24efd9b20c9092b062188 #Id- 329132 2e4d9e0b2035c4259270281306f9bf9d #Id- 30353 cbea84045b9bc34def43f667db8cddc5 #Id- 135199 f3fd7646f5d0a0e6063fe554f6763839 #Id- 328680 3999cc9430675d26184b8f91bf750929 #Id- 329904 2beda913b86e79dd327abe31d84fd86b #Id- 324685 0fe3142773a63e37cdfa9dc663a46dc4 #Id- 327624 194907205353e00a09a8a31523342e53 #Id- 142119 2fe1499ddc099279a9ab1f81abdf56c5 #Id- 322665 888d5ef949daf8f2a76a083d296679d3 #Id- 327570 4126cec052e674c80a45a5c9b7609a29 #Id- 316800 9260359f41a850e2786529c5e4577763 #Id- 326935 64e4ec5d52bc8358dbf8e2e03715195b #Id- 326960 0c9516387244e1a5790e53046f46347b #Id- 329808 fbdadc1559e7a8911207bb3b5dd3d698 #Id- 327725 1f06763a24315cfd51e6610a29383da2 #Id- 329892 9b7b7227d5490fae95d6441add10ab6b #Id- 19064 68b331e542b8a464a8603f583d1fe18d #Id- 50327 abd41f13d55d21a5487343b45353fb91 #Id- 317691 359baf4659b59f4f60dbe1e879c86c8d #Id- 330047 d99e0a76a502a58471889e23010a470f #Id- 327058 ba6eaf2e072dba60158b364bb90349ab #Id- 327547 c061e8777b2cdad0bd0f8619ca5988ef #Id- 114363 08a14142468aa643dcaa74a5c31c82ed #Id- 327620 03bb4ca376c67ab7c8d5a6448ee697b2 #Id- 327986 b5a95a21c14fd333f9b083d5bbbf4133 #Id- 327652 ef4cf7399e999d6ba09a2598e3f4fbbe #Id- 329048 40583c3d73257338bef0063c2d083021 #Id- 329568 02fd33685a6d759c370b6395d6b0686a #Id- 329589 a931863d4dcc22b40b532e17867b935f #Id- 329069 04079e07a832ba95965f71beed17f5e5 #Id- 329461 bce2bd27059af0751ea65211028c8d8c #Id- 12621 6e990bf39ad15f7ffc1889cb7648e40d #Id- 41376 c27b1f6d214424f8af59cba731443575 #Id- 325950 bfe66f498a8ccad71feb7fdef47f5e57 #Id- 326653 97e56da40ed79c733cc3f02095ec54e5 #Id- 328956 e9a32af85df4ca7128bf77e534a2031e #Id- 327575 cb77ed098022f9f1a83aae3bfe4be532 #Id- 327287 959e3f33695671e30f4b4d2e4204fa72 #Id- 137497 184ef01563a8da23d1e09d1deb084e98 #Id- 322241 6b202567734b09a156ce2e0fb383cfa7 #Id- 327972 9488c53c7fadc04584c327fcd2e21033 #Id- 326246 c0255f8d39360fdd00ae336aff2dcc61 #Id- 327003 e2e14f131c8ae8600666a2bc53f7d1f8 #Id- 325026 5ec547877382b7278d6ef218b40e647b #Id- 326506 ddc1a207320a06013d100502200f1ec3 #Id- 328875 1cea81f8cc79bdd5c4aba492a4b8a37d #Id- 328698 0b5f6f9f4c5e1bfd870c3783af76cda1 #Id- 50532 4e138557b643a2dcb1e8dd54ebc25408 #Id- 100090 8d0a85ac0ab5293a64034d168238da65 #Id- 314124 025a1b0047265407f321e95a160d358c #Id- 322138 66d3f5bd2d764bc25352e2eb0e5f258a #Id- 329177 9809a26f5dd8901a1f7c50b2919b2cba #Id- 328306 533c53a810cc46488a505fb6567ec1e6 #Id- 165818 12409eee5369a8be6712230ecf3501d8 #Id- 323332 24344df8bb80797e899aaffce5b6837d #Id- 323728 0046f4ee273c98598573179ad4192917 #Id- 328123 ba0c5ff7b91758fca05e2a7888448e9d #Id- 328270 5770a3d3a27571a6913a97fbbcc4ce01 #Id- 327901 8d7b5c6f1e000301b0f57561616d2403 #Id- 329153 6cf8b8e6cc3f343a8e8210afeb864fe9 #Id- 328165 2e853f8f2ecd24c00ba9b281a2c89389 #Id- 329139 5f904810d19538b1e9ad2d1be2aaef31 #Id- 326865 bec146f72f27ea1eb8ff74cc644d3f1c #Id- 329698 9b37f04fa136c47a96d42b4add862344 #Id- 331552 99ac7954c5303b2d351a69cbc31a99b4 #Id- 329621 bb23dadc5edb6af3094d3001c963cbfc #Id- 330439 102e80c57a2809a1ec4ca2a0e5cf6f2e #Id- 291935 d9be7384ee81a6e86ce3473eae63016c #Id- 107122 c45db716e9db3c33c977ee389c441c33 #Id- 325759 00a259217540dc89366a8978c1ad639a #Id- 325628 6dd2a30307ec7e9e5af526163797b384 #Id- 324357 d6ea3196ac922c38d8f0621533037363 #Id- 326103 6284726d4f8e8307ee0ecc25268519a7 #Id- 327107 1503b01ed6b526717f8dbfffdd1f6240 #Id- 329498 f341d187b579745c242afb8af8c751af #Id- 330758 9bebf3096dd152fce70ae5550a975379 #Id- 319466 0e05e23a262fa123a1c7c53f1687a5db #Id- 326230 e1dfdf233caac1f4d661dfff1c51114d #Id- 324103 15ee056789aaed57a81a96184eaa1a61 #Id- 329147 296c5d2415413770153e4b59fd14b757 #Id- 327554 ba553710e173e8556df696b1864ddfd2 #Id- 201470 c17670272f5e022cc39981af5d5c475b #Id- 327155 4c89cbb3d655484f53e21b0a7f0da476 #Id- 328351 5a9369df962218d58fe46644a1e2a0e2 #Id- 326057 06fef68f77964974821000d867b4b7b8 #Id- 328180 db41ffc177aa7ed4214cce312302a97e #Id- 328790 1893c723feaae0f1f2926f48abc2f3c0 #Id- 329048 6cc32fa50eeb784bd76c257a2fc47adb #Id- 317683 49c305d8a392759fc49941bb3c2c0761 #Id- 329014 7ba5b599bb775900efc17fd7148ce12f #Id- 12630 5c97b0a0cea9a79cc1092c090a1ccc45 #Id- 56950 ecdc97be83edcec70c927e4f7f864c7d