Pull to refresh
4
0
Send message

Я не программирую на Java, но если отойти от условий задачи, мне ваш код кажется не очень удачным даже по структуре и компановке. Тем не менее, давайте пройдемся по условиям задачи, как я их понял, и почему я считаю что вы им неудовлетворили.

1.

You need to write a CLI program that extracts files from the provided file based on the provided format. See sample output for the sample above. You must not guess input file format and the program should allow the user to specify input format in some way, as a command line argument for example.

На вход подается eml или zip файл, требуется распаковать вложенные в него файлы. Мне недоступен упомянутый пример, поэтому не знаю хотят ли они сразу распаковать все файлы рекурсивно, или только те что непосредственно вложены в указанный файл. Но не имея вводных, придерживаюсь правила: если что-то не обговорено в условиях задачи, то оно реализуется на усмотрение разработчика. Чтобы снизить уровень неопределенности тут, я бы ввел параметр -R,--recursive. Но вне зависимости от этого,
мы имеем дело, по сути, с древом архивов. Мне кажется логичным распаковать его в древо папок, чтобы как минимум можно было собрать все обратно без потерь, но это так же не обговорено, поэтому пусть еще будет параметр --flat, при указании которого все распаковывается в одну папку (теоретически они могли и собирать все из одной папки).

Вы решили всегда все распаковывать в одну папку, при этом:

  • Вы распаковываете только eml файлы вложенные в eml файлы;

  • Файлы вложенные в zip вы всегда пишете во временный payload.eml. Zip файлы вложенные в eml вы всегда пишете во временный payload.zip, при чем учитывая что вы идете рекурсивно сразу на максимальную глубину вложенности, вы рано или поздно начнете перезаписывать временный файл, для которого уже открыт FileInputStream выше по рекурсии, и вы не закончили - фатальная логическая ошибка.

  • Если eml вложенный в eml не имеет имени, то будет назван filename_collision_{N}.eml, не смотря на то что коллизии нет.

  • Если eml вложенный в eml имеет имя, но файл с ним уже есть, то тоже filename_collision_{N}.eml - теряем исходное имя.

2.

Let’s assume that someone could execute the following operations for arbitrary number of times in a random order:

- Attach EML or ZIP file to the email

- Archive list of emails to the root folder of ZIP archive So the sequence of operations is a storing format for the original set of files.

So the sequence of operations is a storing format for the original set of files.

Они говорят указали что конечный файл формируется двумя операциями выполненными в произвольной последовательности и произвольном количестве:

  • Добавить .eml или .zip в .eml;

  • Архивировать список .eml в корневую папку .zip;

соответственно формат файла отражает последовательность действий пользователя, (что не совсем правда) но как минимум это намекает на то что сначала нужно распаковать все файлы из .zip, и уже потом углубляться дальше в eml. Идти по уровням вложенности в принципе эффективнее, чем рекурсия до максимальной вложенности и обратно (у вас и это не работает), потому что так мы потенциально могли бы распараллелить обработку файлов. Если организовать распаковку файлов как список задач, расширяемый на каждом последующем уровне вложенности (если --recursive), то в минимальной реализации мы можем их обрабатывать последовательно, но у нас уже есть задел как для последующего распараллеливания, так и для возможности диалога с пользователем для каждого из файлов, например если надо перезаписать.

3.

Solution should have quite good quality, ... be able to work with real-life emails (as this one) and quite large ZIP archives.

Программа должна быть качественной и готовой к использованию (large files - это всегда про потоковую обработку, тут у вас проблемы нет). В моем понимании это значит что обработаны основные логические ошибки, но ваша кидает исключения на каждый чих. При чем, половина вашего кода - это попытка избежать логических исключений типа FileNotFoundException кидая вместо них критические, неловимые. Чаще всего IllegalArgumentException, который по вашему коду может означать и что на вход некорректный файл подали, и что на каком-то уровне вложенности файл некорректный. К примеру, вы проверяете является ли файл zip архивом или нет, и потом (в зависимости от функции) кидаете InvalidArgumentException - зачем? Если формат неверный, вызовы конструкторов FileInputStream, ZipInputStream, и MimeMessage выкинули бы как минимум более разборчивые исключения, которые можно было обработать выше. А в идеале обработать и их внутри метода, обернув в ваши логические исключения, по которым вы будете строить обработку ошибок выше.
Ощущение что вы воспринимаете нотацию исключений в Java скорее как раздражитель, и боретесь с ним.

4.

it should be covered by tests

От вас просили покрытый тестами код, но тесты ваши я даже смотреть не стал, так как сам код изначально непригоден для юнит тестов. У вас практически каждый метод работает с файлами, а единственная выведенная в программе абстрактция, - CLIParameters, почему-то прокинута везде где только можно. Даже если отбросить то что методы FileUtils.getOutputDirectory и FileUtils.getSourceFile вовсе не нужны, зачем требовать всю сущность CLIParameters на вход, вы же работаете с единственным параметром, его и требуйте - вам же еще тесты писать, если успеете.

У меня был cybermaster, и при том что я проводил за лего миллионы часов, и программировать тоже начал в школьные годы, он меня не заинтересовал.

Клонировать эти карты мешает сертификат, который подписан сертификатом эмитента, который, в свою очередь, подписан сертификатом платежной системы. И все эти десятки сертификатов платежных систем есть в терминале, чтобы проверить аутентичность карты. Это не привычные всем x.509, а проприетарные форматы, и опять же свои у каждой платежки. А так же уникальные карточные ключи, которые используются, например, для расчета криптограммы, которая аутентифицирует карту.
Но общение на логическом уровне абсолютно никак не зашифровано, и это никак не помогает клонировать карту.

Но разумеется, основная работа выполняется на логическом уровне, проверка карты и выполнение платежа довольно сложный процесс, в котором также задействовано шифрование.

На самом деле это совсем не сложный процесс, обычный APDU обмен — запрос-ответ к карте с набором полей в ASN.1(BER-TLV) формате, как и на большинстве других смарт карт. Стандарты в открытом доступе, и никакого шифрования там тоже нет, разве что подсчет криптограммы на одном из этапов. Протоколы, на логическом уровне, у каждой из платежных систем чуть разные, и кол-во обмениваемых сообщений тоже будет разное.

Существует вектор атаки, где перехватив этот обмен с терминалом, можно подтвердить любую другую операцию на другом терминале, но на практике это очень сложно осуществить.

По поводу лимитов по бесконтактной оплате — это рекомендация платежной системы, но не требование, карта и терминал обмениваются своими требованиями к проверке владельца карты, и в целом могут решить не требовать пин для любой суммы. Эта рекомендация вытекает из правил, установленных платежной системой, по возмещению средств в случае мошенничества. Если рассматривать конкретно бесконтакт с подписью и лимит в 1000 рублей, то в случае фрода все что до 1000 рублей ложится на плечи эмитента, больше — на мерчанта, поэтому мерчант заинтересован в том чтобы запросить у вас пин.

В большинстве случаев, некий rule of thumb, — это мерчант должен доказать что он убедился что вы действительно владелец карты, иначе он несет убытки. Именно для этого на задней стороне карты есть место для подписи — продавец, в теории, обязан сверять подписи на карте и чеке.
При записи в stream я намеренно не использовал конструкцию using (вызов метода Dispose у streamWriter портит мой MemoryStream)

В таких случаях следует использовать конструктор StreamWriter с параметром leaveOpen, в который соответственно передать true. Тогда при диспозе райтера, сам стрим диспозится не будет. :)
Подозреваю что описан ваш реальный опыт, так как попадался на двойной заказ такси с Uber Russia в декабре:
Вызвал такси, через пару минут приложение перестало показывать водителя, подумал что водитель отменил, а я не заметил сообщения, заказал еще раз. В итоге в истории две поездки с разницей в несколько минут: первая показывает правильные адреса, но оборвалась на пол пути; вторая доехала куда надо, но в адресах показывает что заказ был с запада Москвы на юг Гонг Конга.
По ссылке что приведена в статье написано
To get started with the Quantum Katas, you'll first need to install the Quantum Development Kit, available for Windows 10, macOS, and for Linux.


И руководство по установке:
docs.microsoft.com/en-us/quantum/quantum-installconfig?view=qsharp-preview&tabs=tabid-vscode
Знаете, у меня был опыт создания ООО в России и в Грузии. Так вот:
— В России уже за первый месяц было израсходавоно более 4 пачек бумаги A4 (стандартных, 500 листов) на различные документы, приказы и отчетности. Сколько подписей и печатей нужно было проставить даже вспоминать не хочется.
— В Грузии регистрация компании свелась к походу в местный центр одного окна, где девушка заполнила с нами форму о регистрации компании, через 2 дня мы получили СМС о том что все готово и пришли забрать документы, открыли счет в банке, и далее все наше общение с властью происходит удаленно, и заключается лишь в подании налоговой отчетности онлайн.
Меня больше смущает что ни справа, ни слева не определился знак пешеходного перехода.
Справа показывает номер как у знака выше — 4.1.1 (движение прямо), а 31.2 вовсе отсутствует в ПДД.
Это еще один довод за Амстердам, но пугает одно: смогу ли я привыкнуть к принципиально другому уровню жизни. Амстердам — очень дорогой город. А в Москве, и в Праге, как известно, senior/lead developer живет очень даже комфортно, ни в чем себе не отказывая.
Общество сильно отличается, и поэтому есть сомнения.
Сижу с двумя оферами на руках: в Праге и в Амстердаме. И всю голову уже сломал… Большие компании, хорошие предложения. Гросс зарплаты сильно разнятся, но чистыми как-то получается что нет существенной разницы, что тут в Москве, что там… Вот только стоимость жизни в Амстердаме существенно выше, но Нидерланды всегда были моей любимой европейской страной.

И вот никак не могу определится: ни в чем себе не отказывать в Праге, или размеренная жизнь в развитом Амстердаме.
«Расчетные сети вроде Visa и MasterCard считают EMV более перспективной технологией...»

Что-то тут не так, Apple Pay и работает по EMV стандартам, через сервисы MDES и VTS у мастеркарда и визы соответствеено. Никаких обновлений со сторрны терминала не требуется.

Собственно, как и samsung pay, который тоже много с кем сейчас ведет переговоры.
Почему не смогут? Они выпишут еще один сертификат на ваш домен, но со своим приватным ключем. Если их CA будет в доверенных, они и до гугла траффик читать смогут, и все равно в браузере будет зеленый замочек.
А у мастера в банк эмитент прилетает все та же сотка, и в их подобии SMS все равно на стороне МПС она разбивается на обычную авторизацию + клиринговую транзакцию.
Про 0200 верно, правда SMS обязателен как раз только у визы. А чтобы где-то использовали 1*** 2*** сообщения я ни разу не видел, ни в общении с платежками, ни по меж-хосту, ни на POS-ах.
У сбера не свои процессинговые системы, тоже от вендоров. OpenWay и вроде BPC.
Я бы сказал наоборот, взаимодействия между банками намного проще чем банка с его банкоматами, развернутый ответ внизу.
«могут снимать практически неограниченные суммы денег из банкоматов, принадлежащих другим банкам»

Принцип работы кроется в этой фразе, сейчас объясню:

Заходить со стороны общения с банкоматамив рамках одного банка — это достаточно сложно: мало того что есть много протоколов обмена, многие процессинговые системы еще и ведут учет счетчиков кассет с наличностью на банкомате, а инкасаторы их в свою очередь сверяют, подвох был бы замечен достаточно быстро.

Но, у всех процессинговых систем есть одна общая точка входа — каналы платежных систем, общение по этом каналам никак не шифруется и происходит по протоколу ISO8583. Когда вы снимаете деньги в банкомате, проходит авторизация — сообщение 0100, в котором ваш банк эмитент проверяет пин блок, средства на вашем счету и т.п. Если банкомат по каким-то причинам не получил ответ от вашего банка, или же не смог выдать наличность (застряло в кассете, не открылась шторка, выключилось питание..), то автоматически инициируется процедура отката — сообщение 0420 (reversal advice).

Распознать операцию с банкомата достаточно просто, у них в авторизациях стоит MCC (Merchant Category Code) 6011, соответственно если как-то встать между процессинговой системой банка и платежной системой, можно отловить снятие наличных, и послать в процессинговую систему эмитента сообщение об отмене, таким образом банк эмитент считает что операция была отменена, а банк обслуживающий банкомат напротив думает что с клиента были сняты деньги.

Но процедура реального расчета между банками проходит позже… у Visa авторизации с банкомата сразу считаются финансовыми и не требуют подтверждения, а например у MasterCard ожидается клиринг, который может прийти через несколько дней. Вот в этот период карточка злоумышленника практически безлимитна, но как только придет клиринг она уйдет в технический овердрафт.
Да, верно, деньги заблокировали, но примерно через месяц ваш банк сам их разблокирует. Так как вам скорее всего не сообщат что их разблокировали (только в выписке такие моменты могут отражаться), вы можете этого не заметить. А вот когда их опять спишут, но уже окончательно, вы можете заподозрить неладное…
Вы могли провести авторизацию год назад, и вам даже смска приходила. Но реально деньги за нее спишут только сейчас, уже после того как вы заблокировали карту.
В действительности, на систематической основе сталкивался с таким только на ямайке. Были мерчанты с очень старыми терминалами не умеющими реконсилироваться, которые их очень редко использовали, но все-таки использовали. Поэтому раз в пол года-год продавцы с распечатанным чеком ползли в банк, и только тогда с владельцев карт реально списывали деньги.

Information

Rating
Does not participate
Registered
Activity