LyoKICogJFJDU0lkOiB4Yy9saWIvZm9udGNvbmZpZy9zcmMvZmNkaXIuYyx2IDEuOSAyMDAyLzA4LzMxIDIyOjE3OjMyIGtlaXRocCBFeHAgJAogKgogKiBDb3B5cmlnaHQgqSAyMDAwIEtlaXRoIFBhY2thcmQKICoKICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSwgYW5kIHNlbGwgdGhpcyBzb2Z0d2FyZSBhbmQgaXRzCiAqIGRvY3VtZW50YXRpb24gZm9yIGFueSBwdXJwb3NlIGlzIGhlcmVieSBncmFudGVkIHdpdGhvdXQgZmVlLCBwcm92aWRlZCB0aGF0CiAqIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFwcGVhciBpbiBhbGwgY29waWVzIGFuZCB0aGF0IGJvdGggdGhhdAogKiBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIGFwcGVhciBpbiBzdXBwb3J0aW5nCiAqIGRvY3VtZW50YXRpb24sIGFuZCB0aGF0IHRoZSBuYW1lIG9mIEtlaXRoIFBhY2thcmQgbm90IGJlIHVzZWQgaW4KICogYWR2ZXJ0aXNpbmcgb3IgcHVibGljaXR5IHBlcnRhaW5pbmcgdG8gZGlzdHJpYnV0aW9uIG9mIHRoZSBzb2Z0d2FyZSB3aXRob3V0CiAqIHNwZWNpZmljLCB3cml0dGVuIHByaW9yIHBlcm1pc3Npb24uICBLZWl0aCBQYWNrYXJkIG1ha2VzIG5vCiAqIHJlcHJlc2VudGF0aW9ucyBhYm91dCB0aGUgc3VpdGFiaWxpdHkgb2YgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UuICBJdAogKiBpcyBwcm92aWRlZCAiYXMgaXMiIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LgogKgogKiBLRUlUSCBQQUNLQVJEIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIIFJFR0FSRCBUTyBUSElTIFNPRlRXQVJFLAogKiBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MsIElOIE5PCiAqIEVWRU5UIFNIQUxMIEtFSVRIIFBBQ0tBUkQgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgSU5ESVJFQ1QgT1IKICogQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST00gTE9TUyBPRiBVU0UsCiAqIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1IgT1RIRVIKICogVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUgogKiBQRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLgogKi8KCiNpbmNsdWRlICJmY2ludC5oIgojaW5jbHVkZSA8ZGlyZW50Lmg+CgpzdGF0aWMgRmNCb29sCkZjRmlsZUlzRGlyIChjb25zdCBGY0NoYXI4ICpmaWxlKQp7CiAgICBzdHJ1Y3Qgc3RhdAkgICAgc3RhdGI7CgogICAgaWYgKHN0YXQgKChjb25zdCBjaGFyICopIGZpbGUsICZzdGF0YikgIT0gMCkKCXJldHVybiBGY0ZhbHNlOwogICAgcmV0dXJuIFNfSVNESVIoc3RhdGIuc3RfbW9kZSk7Cn0KCkZjQm9vbApGY0ZpbGVTY2FuQ29uZmlnIChGY0ZvbnRTZXQJKnNldCwKCQkgIEZjU3RyU2V0CSpkaXJzLAoJCSAgRmNHbG9iYWxDYWNoZSAqY2FjaGUsCgkJICBGY0JsYW5rcwkqYmxhbmtzLAoJCSAgY29uc3QgRmNDaGFyOAkqZmlsZSwKCQkgIEZjQm9vbAlmb3JjZSwKCQkgIEZjQ29uZmlnCSpjb25maWcpCnsKICAgIGludAkJCWlkOwogICAgRmNDaGFyOAkJKm5hbWU7CiAgICBGY1BhdHRlcm4JCSpmb250OwogICAgRmNCb29sCQlyZXQgPSBGY1RydWU7CiAgICBGY0Jvb2wJCWlzRGlyOwogICAgaW50CQkJY291bnQgPSAwOwogICAgRmNHbG9iYWxDYWNoZUZpbGUJKmNhY2hlX2ZpbGU7CiAgICBGY0dsb2JhbENhY2hlRGlyCSpjYWNoZV9kaXI7CiAgICBGY0Jvb2wJCW5lZWRfc2NhbjsKICAgIAogICAgaWYgKGNvbmZpZyAmJiAhRmNDb25maWdBY2NlcHRGaWxlbmFtZSAoY29uZmlnLCBmaWxlKSkKCXJldHVybiBGY1RydWU7CgogICAgaWYgKGZvcmNlKQoJY2FjaGUgPSAwOwogICAgaWQgPSAwOwogICAgZG8KICAgIHsKCW5lZWRfc2NhbiA9IEZjVHJ1ZTsKCWZvbnQgPSAwOwoJLyoKCSAqIENoZWNrIHRoZSBjYWNoZQoJICovCglpZiAoY2FjaGUpCgl7CgkgICAgaWYgKChjYWNoZV9maWxlID0gRmNHbG9iYWxDYWNoZUZpbGVHZXQgKGNhY2hlLCBmaWxlLCBpZCwgJmNvdW50KSkpCgkgICAgewoJCS8qCgkJICogRm91bmQgYSBjYWNoZSBlbnRyeSBmb3IgdGhlIGZpbGUKCQkgKi8KCQlpZiAoRmNHbG9iYWxDYWNoZUNoZWNrVGltZSAoZmlsZSwgJmNhY2hlX2ZpbGUtPmluZm8pKQoJCXsKCQkgICAgbmFtZSA9IGNhY2hlX2ZpbGUtPm5hbWU7CgkJICAgIG5lZWRfc2NhbiA9IEZjRmFsc2U7CgkJICAgIEZjR2xvYmFsQ2FjaGVSZWZlcmVuY2VkIChjYWNoZSwgJmNhY2hlX2ZpbGUtPmluZm8pOwoJCSAgICAvKiAiLiIgbWVhbnMgdGhlIGZpbGUgZG9lc24ndCBjb250YWluIGEgZm9udCAqLwoJCSAgICBpZiAoRmNTdHJDbXAgKG5hbWUsIEZDX0ZPTlRfRklMRV9JTlZBTElEKSAhPSAwKQoJCSAgICB7CgkJCWZvbnQgPSBGY05hbWVQYXJzZSAobmFtZSk7CgkJCWlmIChmb250KQoJCQkgICAgaWYgKCFGY1BhdHRlcm5BZGRTdHJpbmcgKGZvbnQsIEZDX0ZJTEUsIGZpbGUpKQoJCQkJcmV0ID0gRmNGYWxzZTsKCQkgICAgfQoJCX0KCSAgICB9CgkgICAgZWxzZSBpZiAoKGNhY2hlX2RpciA9IEZjR2xvYmFsQ2FjaGVEaXJHZXQgKGNhY2hlLCBmaWxlLAoJCQkJCQkgICAgICAgc3RybGVuICgoY29uc3QgY2hhciAqKSBmaWxlKSwKCQkJCQkJICAgICAgIEZjRmFsc2UpKSkKCSAgICB7CgkJaWYgKEZjR2xvYmFsQ2FjaGVDaGVja1RpbWUgKGNhY2hlX2Rpci0+aW5mby5maWxlLCAKCQkJCQkgICAgJmNhY2hlX2Rpci0+aW5mbykpCgkJewoJCSAgICBmb250ID0gMDsKCQkgICAgbmVlZF9zY2FuID0gRmNGYWxzZTsKCQkgICAgRmNHbG9iYWxDYWNoZVJlZmVyZW5jZWQgKGNhY2hlLCAmY2FjaGVfZGlyLT5pbmZvKTsKCQkgICAgaWYgKCFGY1N0clNldEFkZCAoZGlycywgZmlsZSkpCgkJCXJldCA9IEZjRmFsc2U7CgkJfQoJICAgIH0KCX0KCS8qCgkgKiBOb3RoaW5nIGluIHRoZSBjYWNoZSwgc2NhbiB0aGUgZmlsZQoJICovCglpZiAobmVlZF9zY2FuKQoJewoJICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX1NDQU4pCgkgICAgewoJCXByaW50ZiAoIlx0U2Nhbm5pbmcgZmlsZSAlcy4uLiIsIGZpbGUpOwoJCWZmbHVzaCAoc3Rkb3V0KTsKCSAgICB9CgkgICAgZm9udCA9IEZjRnJlZVR5cGVRdWVyeSAoZmlsZSwgaWQsIGJsYW5rcywgJmNvdW50KTsKCSAgICBpZiAoRmNEZWJ1ZyAoKSAmIEZDX0RCR19TQ0FOKQoJCXByaW50ZiAoImRvbmVcbiIpOwoJICAgIGlzRGlyID0gRmNGYWxzZTsKCSAgICBpZiAoIWZvbnQgJiYgRmNGaWxlSXNEaXIgKGZpbGUpKQoJICAgIHsKCQlpc0RpciA9IEZjVHJ1ZTsKCQlyZXQgPSBGY1N0clNldEFkZCAoZGlycywgZmlsZSk7CgkgICAgfQoJICAgIC8qCgkgICAgICogVXBkYXRlIHRoZSBjYWNoZQoJICAgICAqLwoJICAgIGlmIChjYWNoZSAmJiBmb250KQoJICAgIHsKCQlGY0NoYXI4CSp1bnBhcnNlOwoKCQl1bnBhcnNlID0gRmNOYW1lVW5wYXJzZSAoZm9udCk7CgkJaWYgKHVucGFyc2UpCgkJewoJCSAgICAodm9pZCkgRmNHbG9iYWxDYWNoZVVwZGF0ZSAoY2FjaGUsIGZpbGUsIGlkLCB1bnBhcnNlKTsKCQkgICAgRmNTdHJGcmVlICh1bnBhcnNlKTsKCQl9CgkgICAgfQoJfQoJLyoKCSAqIEFkZCB0aGUgZm9udAoJICovCglpZiAoZm9udCkKCXsKCSAgICBpZiAoIUZjRm9udFNldEFkZCAoc2V0LCBmb250KSkKCSAgICB7CgkJRmNQYXR0ZXJuRGVzdHJveSAoZm9udCk7CgkJZm9udCA9IDA7CgkJcmV0ID0gRmNGYWxzZTsKCSAgICB9Cgl9CglpZCsrOwogICAgfSB3aGlsZSAoZm9udCAmJiByZXQgJiYgaWQgPCBjb3VudCk7CiAgICByZXR1cm4gcmV0Owp9CgpGY0Jvb2wKRmNGaWxlU2NhbiAoRmNGb250U2V0CSAgICAqc2V0LAoJICAgIEZjU3RyU2V0CSAgICAqZGlycywKCSAgICBGY0dsb2JhbENhY2hlICAgKmNhY2hlLAoJICAgIEZjQmxhbmtzCSAgICAqYmxhbmtzLAoJICAgIGNvbnN0IEZjQ2hhcjggICAqZmlsZSwKCSAgICBGY0Jvb2wJICAgIGZvcmNlKQp7CiAgICByZXR1cm4gRmNGaWxlU2NhbkNvbmZpZyAoc2V0LCBkaXJzLCBjYWNoZSwgYmxhbmtzLCBmaWxlLCBmb3JjZSwgMCk7Cn0KCiNkZWZpbmUgRkNfTUFYX0ZJTEVfTEVOCSAgICA0MDk2CgovKgogKiBTY2FuICdkaXInLCBhZGRpbmcgZm9udCBmaWxlcyB0byAnc2V0JyBhbmQKICogc3ViZGlyZWN0b3JpZXMgdG8gJ2RpcnMnCiAqLwoKRmNCb29sCkZjRGlyU2NhbkNvbmZpZyAoRmNGb250U2V0CSpzZXQsCgkJIEZjU3RyU2V0CSpkaXJzLAoJCSBGY0dsb2JhbENhY2hlICAqY2FjaGUsCgkJIEZjQmxhbmtzCSpibGFua3MsCgkJIGNvbnN0IEZjQ2hhcjggICpkaXIsCgkJIEZjQm9vbAkJZm9yY2UsCgkJIEZjQ29uZmlnCSpjb25maWcpCnsKICAgIERJUgkJCSpkOwogICAgc3RydWN0IGRpcmVudAkqZTsKICAgIEZjQ2hhcjgJCSpmaWxlOwogICAgRmNDaGFyOAkJKmJhc2U7CiAgICBGY0Jvb2wJCXJldCA9IEZjVHJ1ZTsKCiAgICBpZiAoY29uZmlnICYmICFGY0NvbmZpZ0FjY2VwdEZpbGVuYW1lIChjb25maWcsIGRpcikpCglyZXR1cm4gRmNUcnVlOwoKICAgIGlmICghZm9yY2UpCiAgICB7CgkvKgoJICogQ2hlY2sgZm9udHMuY2FjaGUtPHZlcnNpb24+IGZpbGUKCSAqLwoJaWYgKEZjRGlyQ2FjaGVSZWFkRGlyIChzZXQsIGRpcnMsIGRpciwgY29uZmlnKSkKCXsKCSAgICBpZiAoY2FjaGUpCgkJRmNHbG9iYWxDYWNoZVJlZmVyZW5jZVN1YmRpciAoY2FjaGUsIGRpcik7CgkgICAgcmV0dXJuIEZjVHJ1ZTsKCX0KICAgIAoJLyoKCSAqIENoZWNrIH4vLmZvbnRzLmNhY2hlLTx2ZXJzaW9uPiBmaWxlCgkgKi8KCWlmIChjYWNoZSAmJiBGY0dsb2JhbENhY2hlU2NhbkRpciAoc2V0LCBkaXJzLCBjYWNoZSwgZGlyLCBjb25maWcpKQoJICAgIHJldHVybiBGY1RydWU7CiAgICB9CiAgICAKICAgIC8qIGZyZWVkIGJlbG93ICovCiAgICBmaWxlID0gKEZjQ2hhcjggKikgbWFsbG9jIChzdHJsZW4gKChjaGFyICopIGRpcikgKyAxICsgRkNfTUFYX0ZJTEVfTEVOICsgMSk7CiAgICBpZiAoIWZpbGUpCglyZXR1cm4gRmNGYWxzZTsKCiAgICBzdHJjcHkgKChjaGFyICopIGZpbGUsIChjaGFyICopIGRpcik7CiAgICBzdHJjYXQgKChjaGFyICopIGZpbGUsICIvIik7CiAgICBiYXNlID0gZmlsZSArIHN0cmxlbiAoKGNoYXIgKikgZmlsZSk7CiAgICAKICAgIGlmIChGY0RlYnVnICgpICYgRkNfREJHX1NDQU4pCglwcmludGYgKCJcdFNjYW5uaW5nIGRpciAlc1xuIiwgZGlyKTsKCQogICAgZCA9IG9wZW5kaXIgKChjaGFyICopIGRpcik7CiAgICAKICAgIGlmICghZCkKICAgIHsKCWZyZWUgKGZpbGUpOwoJLyogRG9uJ3QgY29tcGxhaW4gYWJvdXQgbWlzc2luZyBkaXJlY3RvcmllcyAqLwoJaWYgKGVycm5vID09IEVOT0VOVCkKCSAgICByZXR1cm4gRmNUcnVlOwoJcmV0dXJuIEZjRmFsc2U7CiAgICB9CiAgICB3aGlsZSAocmV0ICYmIChlID0gcmVhZGRpciAoZCkpKQogICAgewoJaWYgKGUtPmRfbmFtZVswXSAhPSAnLicgJiYgc3RybGVuIChlLT5kX25hbWUpIDwgRkNfTUFYX0ZJTEVfTEVOKQoJewoJICAgIHN0cmNweSAoKGNoYXIgKikgYmFzZSwgKGNoYXIgKikgZS0+ZF9uYW1lKTsKCSAgICByZXQgPSBGY0ZpbGVTY2FuQ29uZmlnIChzZXQsIGRpcnMsIGNhY2hlLCBibGFua3MsIGZpbGUsIGZvcmNlLCBjb25maWcpOwoJfQogICAgfQogICAgZnJlZSAoZmlsZSk7CiAgICBjbG9zZWRpciAoZCk7CiAgICAvKgogICAgICogTm93IHRoYXQgdGhlIGRpcmVjdG9yeSBoYXMgYmVlbiBzY2FubmVkLAogICAgICogYWRkIHRoZSBjYWNoZSBlbnRyeSAKICAgICAqLwogICAgaWYgKHJldCAmJiBjYWNoZSkKCUZjR2xvYmFsQ2FjaGVVcGRhdGUgKGNhY2hlLCBkaXIsIDAsIDApOwoJCiAgICByZXR1cm4gcmV0Owp9CgpGY0Jvb2wKRmNEaXJTY2FuIChGY0ZvbnRTZXQJICAgICpzZXQsCgkgICBGY1N0clNldAkgICAgKmRpcnMsCgkgICBGY0dsb2JhbENhY2hlICAgICpjYWNoZSwKCSAgIEZjQmxhbmtzCSAgICAqYmxhbmtzLAoJICAgY29uc3QgRmNDaGFyOCAgICAqZGlyLAoJICAgRmNCb29sCSAgICBmb3JjZSkKewogICAgcmV0dXJuIEZjRGlyU2NhbkNvbmZpZyAoc2V0LCBkaXJzLCBjYWNoZSwgYmxhbmtzLCBkaXIsIGZvcmNlLCAwKTsKfQoKRmNCb29sCkZjRGlyU2F2ZSAoRmNGb250U2V0ICpzZXQsIEZjU3RyU2V0ICpkaXJzLCBjb25zdCBGY0NoYXI4ICpkaXIpCnsKICAgIHJldHVybiBGY0RpckNhY2hlV3JpdGVEaXIgKHNldCwgZGlycywgZGlyKTsKfQo=