Лидеры
Популярный контент
Показан контент с высокой репутацией 27.08.2016 во всех областях
-
В 2017 еще пока даже апдейты Берлина не выпустили, когда им успеть новую версию выпустить2 балла
-
Berlin HTTPClient: сломаны Cookies - ошибка в исходном коде
AngryOwl отреагировал Евгений Корепов за вопрос
Начал переносить проекты из XE8 в Berlin, столкнулся с странным затыком в простеньком коде - делаем запрос на сайт, получаем куки, делаем post авторизацию, получаем редирект, если все хорошо, то октрываем страницу из header Location. Выяснилось что не смотря на HTTPClient.AllowCookies:=True, в HTTPResponse.Cookies всегда пустота. Пришлось копать исходники. Вот что обнаружилось в source\rtl\net\System.Net.HttpClient.pas: procedure THTTPClient.ExecuteHTTPInternal(const ARequest: IHTTPRequest; const AContentStream: TStream; const AResponse: IHTTPResponse); var LRequest: THTTPRequest; LResponse: THTTPResponse; State: THTTPState; LExecResult: TExecutionResult; LClientCertificateList: TCertificateList; OrigSourceStreamPosition: Int64; OrigContentStreamPosition: Int64; OrigContentStreamSize: Int64; Status: Integer; LCookieHeader: string; begin LResponse := AResponse as THTTPResponse; LRequest := ARequest as THTTPRequest; OrigSourceStreamPosition := 0; if LRequest.FSourceStream <> nil then OrigSourceStreamPosition := LRequest.FSourceStream.Position; if AContentStream <> nil then begin OrigContentStreamPosition := AContentStream.Position; OrigContentStreamSize := AContentStream.Size; end else begin OrigContentStreamPosition := 0; OrigContentStreamSize := 0; end; State := Default(THTTPState); LClientCertificateList := TCertificateList.Create; try while True do begin LRequest.DoPrepare; // Add Cookies if FCookieManager <> nil then begin LCookieHeader := FCookieManager.CookieHeaders(LRequest.FURL); if LCookieHeader <> '' then LRequest.AddHeader('Cookie', LCookieHeader); // do not localize end; if not SetServerCredential(LRequest, LResponse, State) then Break; if not SetProxyCredential(LRequest, LResponse, State) then Break; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Position := OrigSourceStreamPosition; if LResponse <> nil then begin LResponse.FStream.Position := OrigContentStreamPosition; LResponse.FStream.Size := OrigContentStreamSize; end; LExecResult := DoExecuteRequest(LRequest, LResponse, AContentStream); case LExecResult of TExecutionResult.Success: begin if not SameText(LRequest.FMethodString, sHTTPMethodHead) then LResponse.DoReadData(LResponse.FStream); Status := LResponse.GetStatusCode; case Status of 200: begin Break; // Если запрос удачен, то выходим из цикла end; 401: begin State.Status := InternalState.ServerAuthRequired; end; 407: begin State.Status := InternalState.ProxyAuthRequired; end; else begin case Status of 301..304, 307: if FHandleRedirects and (LRequest.FMethodString <> sHTTPMethodHead) then begin Inc(State.Redirections); if State.Redirections > FMaxRedirects then raise ENetHTTPRequestException.CreateResFmt(@SNetHttpMaxRedirections, [FMaxRedirects]); end else Break; else end; State.Status := InternalState.Other; if DoProcessStatus(LRequest, LResponse) then Break; end; end; end; TExecutionResult.ServerCertificateInvalid: begin DoValidateServerCertificate(LRequest); end; TExecutionResult.ClientCertificateNeeded: begin DoNeedClientCertificate(LRequest, LClientCertificateList); end else raise ENetHTTPClientException.CreateRes(@SNetHttpClientUnknownError); end; if AllowCookies then UpdateCookiesFromResponse(LResponse); // Вот эта, критически важная процедура, при Status=200 никогда не выполняется end; // После выхода из цикла попадаем сюда if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Seek(0, TSeekOrigin.soEnd); LResponse.FStream.Position := OrigContentStreamPosition; finally LClientCertificateList.Free; end; end; Т.е. разработчики исключили выполнение UpdateCookiesFromResponse(LResponse), которая помещает куки из ответа в HTTPClient. А вот код из XE8 который нормально работает с Cookies: function THTTPClient.ExecuteHTTPInternal(const ARequest: IHTTPRequest; const AContentStream: TStream): IHTTPResponse; var LRequest: THTTPRequest; LResponse: THTTPResponse; State: THTTPState; LExecResult: TExecutionResult; LClientCertificateList: TCertificateList; OrigSourceStreamPosition: Int64; OrigContentStreamPosition: Int64; OrigContentStreamSize: Int64; Status: Integer; LCookieHeader: string; begin Result := nil; LResponse := nil; LRequest := ARequest as THTTPRequest; OrigSourceStreamPosition := 0; if LRequest.FSourceStream <> nil then OrigSourceStreamPosition := LRequest.FSourceStream.Position; if AContentStream <> nil then begin OrigContentStreamPosition := AContentStream.Position; OrigContentStreamSize := AContentStream.Size; end else begin OrigContentStreamPosition := 0; OrigContentStreamSize := 0; end; State := Default(THTTPState); LClientCertificateList := TCertificateList.Create; try while True do begin LRequest.DoPrepare; // Add Cookies if FCookieManager <> nil then begin LCookieHeader := FCookieManager.CookieHeaders(LRequest.FURL); if LCookieHeader <> '' then LRequest.AddHeader('Cookie', LCookieHeader); // do not localize end; if not SetServerCredential(LRequest, LResponse, State) then Break; if not SetProxyCredential(LRequest, LResponse, State) then Break; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Position := OrigSourceStreamPosition; if LResponse <> nil then begin LResponse.FStream.Position := OrigContentStreamPosition; LResponse.FStream.Size := OrigContentStreamSize; end; LExecResult := DoExecuteRequest(LRequest, LResponse, AContentStream); case LExecResult of TExecutionResult.Success: begin if not SameText(LRequest.FMethodString, sHTTPMethodHead) then LResponse.DoReadData(LResponse.FStream); Status := LResponse.GetStatusCode; case Status of 200: begin Break; end; 401: begin State.Status := InternalState.ServerAuthRequired; end; 407: begin State.Status := InternalState.ProxyAuthRequired; end; else begin case Status of 301..304, 307: if FHandleRedirects and (LRequest.FMethodString <> sHTTPMethodHead) then begin Inc(State.Redirections); if State.Redirections > FMaxRedirects then raise ENetHTTPRequestException.CreateResFmt(@SNetHttpMaxRedirections, [FMaxRedirects]); end else Break; else end; State.Status := InternalState.Other; if DoProcessStatus(LRequest, LResponse) then Break; end; end; end; TExecutionResult.ServerCertificateInvalid: begin DoValidateServerCertificate(LRequest); end; TExecutionResult.ClientCertificateNeeded: begin DoNeedClientCertificate(LRequest, LClientCertificateList); end else raise ENetHTTPClientException.CreateRes(@SNetHttpClientUnknownError); end; end; if LRequest.FSourceStream <> nil then LRequest.FSourceStream.Seek(0, TSeekOrigin.soEnd); if AllowCookies then UpdateCookiesFromResponse(LResponse); // Здесь все верно, процедура за пределами цикла и выполняется всегда когда нужно. finally LClientCertificateList.Free; Result := IHTTPResponse(LResponse); end; end; А теперь вопрос: ну как так то? В продукте за 54 тысячи рублей сильно обидно исправлять такие косяки. Такое ощущение что разраб подрабатывал на стороне в проектах на php и забыл переключится на другой язык, там break прерывает работу аналога case и код работал бы правильно.1 балл -
Как нормально установить Berlin?
zairkz отреагировал Евгений Корепов за тема
Получил сегодня ключи от Берлина, на радостях начал установку. Как и у многих, конфигурация типичная - SSD 128Gb в качестве системного, и большой HDD в качестве рабочего. На SSD было 20 гигов свободного места, студию естественно устанавливал в D:\Embarcadero\Studio\18.0. Установка закончилась падением винды. Убогий установщик Берлина засрал системный диск полностью, распихав по системному диску 30 гигов мусора и обрушил систему. Посмотреть бы в глаза разработчику этого убожества. Почему нельзя ставить студию туда куда указано? Для чего такой кривой интерфейс установщика, скрин прилагаю, надеюсь ниже обезанного пункта в списке ничего нет что мне понадобится. Почему нельзя использовать Application.ProcessMessage для долгих операций, чтоб винда по нескольку раз не говорила что приложение не отвечает, давай ее убъем. Пока складывается ощущение что я выкинул 54 тысячи на ветер, если среда исполнена теми же авторами, то чувствую весь ад еще впереди.1 балл -
Berlin HTTPClient: сломаны Cookies - ошибка в исходном коде
AngryOwl отреагировал Евгений Корепов за вопрос
Оказывается эта проблема была обнаружена еще 26/Apr/16 12:29 AM https://quality.embarcadero.com/browse/RSP-14307 . И пока доступен только патч с хелперами https://quality.embarcadero.com/secure/attachment/17147/RSP14307.patch.zip Написана что проблема решена в Berlin Update 1. Но как понимаю этого апдейта еще не было?1 балл -
[Android] ListView в Берлине
Евгений Корепов отреагировал krapotkin за вопрос
там исходники довольно простые. а исходная идея тут но правильнее будет сделать фреймворк что-то типа relative layout https://developer.android.com/guide/topics/ui/layout/relative.html но там серьезно надо думать, а рук не хватает )))1 балл -
уже более 10 лет я не ставлю крупные программы, особенно делфи и SDK по путям производителей началось это тогда, когда выяснилось, что имена файлов длиннее 255 и среда просто не справляется с ними. а если там кириллица, то шеф, усё пропало.... лучше ставить в корень. SDK ставить отдельно. тоже в корень. а потом просто показать делфи, где они лежат...1 балл
-
Нужен совет "бывалого" разработчика
Andrey Efimov отреагировал Равиль Зарипов (ZuBy) за вопрос
это стандартное поведение1 балл -
Как нормально установить Berlin?
zairkz отреагировал Евгений Корепов за тема
Самое смешное что у меня для таких случаем настроена переменная среды окружения TEMP=D:\Temp\System_Temp\, но видимо писатели не стали парится с их использованием, а написали нечто вроде Куда_срем := Папка_профиля + 'AppData\Local\Temp'; Установить в итоге удалось выделив на системном около 45 гигов. Но мусор на системном диске остался, буду разбираться как его переносить. Интересно, хоть кто нибудь пишет проекты в папке профиля Documents\Embarcadero\Studio\Projects, по станной задумке эмбаркадеры? Нужно больше вложенных папок! Глубже, еще глубже! Все еще не достаточно глубоко! ;-) С трудом нашел Android SDK C:\Users\Public\Documents\Embarcadero\Studio\18.0\CatalogRepository\AndroidSDK-24.3.3_GIB.Build.22858.6822, хотя не уверен что это используемая средой копия, слишком мало вложенных папок, нужно копать глубже ;-)1 балл -
Нужен совет "бывалого" разработчика
Andrey Efimov отреагировал Равиль Зарипов (ZuBy) за вопрос
ну как-бы кнопка назад (vkHardwareBack) выполняет закрытие клавиатуры, нужно всего лишь обработать OnKeyUp и не нужно ничего городить1 балл -
Нужен совет "бывалого" разработчика
Andrey Efimov отреагировал Alexander за вопрос
Слева и справа вверху повесить "плавающие" полупрозрачные кнопки "Ок" и "Отмена"1 балл -
TEdit не понятное удаление последнего символа
Andrey Efimov отреагировал Rusland за вопрос
Попробуйте поставить два Edit-а и переходите с одного на другой и попробуйте удалить последний символ. Спасибо, решение сработало.1 балл -
[Заметка] [Google Play] Ответы на два самых частых вопроса
Andrey Efimov отреагировал Евгений Корепов за тема
Нет, нельзя. Имя пакета это главный идентификатор приложения, создается раз и навсегда. Даже при блокировке приложения и повторной публикации имя пакета нужно другое. Единственное исключение, если вам заблокировали приложение, но вы доказали свою правоту, то спустя неопределенное количество времени (в моем случае почти два месяца), можно опубликовать приложение с тем же именем пакета.1 балл -
[Статья] Публикация приложения в Google Play
Andrey Efimov отреагировал Kitty за тема
Спасибо. значит так: <uses-sdk android:minSdkVersion="19"1 балл -
[Статья] Публикация приложения в Google Play
Andrey Efimov отреагировал Равиль Зарипов (ZuBy) за тема
в androidmanifest.template minSdk1 балл -
[Android] ListView в Берлине
Евгений Корепов отреагировал krapotkin за вопрос
я еще раз положу рабочий проект для Delphi Berlin. там есть отличия от общепринятого метода ListViewTestBerlin.7z1 балл -
Редактор ListView 2 - DynamicAppearance
Евгений Корепов отреагировал Равиль Зарипов (ZuBy) за вопрос
как-то так var iTitle: TListItemText; begin iTitle := AItem.Objects.FindDrawable('Text1') as TListItemText; if iTitle <> nil then iTitle.Width:=ListView5.Width-85; end;1 балл -
Редактор ListView 2 - DynamicAppearance
Евгений Корепов отреагировал Равиль Зарипов (ZuBy) за вопрос
всегда присваивайте в переменную, проверьте на валидность, а потом проводите с ней различные операции. у меня много раз было AV, т.к. "контрол" не был создан1 балл -
https://www.youtube.com/watch?v=ta_N6DSi0Xg с 22 минуты1 балл