Страницы

Поиск по вопросам

пятница, 13 марта 2020 г.

Загрузка файла на сервер - баги, уязвимости

#php #javascript #html #безопасность


На моем сайте есть форма для загрузки файла, в которой у пользователя есть возможность,
написав комментарий, прикрепить файл. Загрузку файла я не контролирую: нет ограничения
по размеру, по типу и т.п. 

Что может злоумышленник сделать с такой загрузкой файла, где нет ни каких ограничений? 
Какие есть еще защиты кроме ограничения по размеру, типу?
    


Ответы

Ответ 1



Злоумышленник при заливке произвольного файла к вам на сервер в принципе может все что угодно. Файл может быть скриптом php или другим видом cgi и дать злоумышленнику полный доступ на ваш хостинг. А может быть каким нибудь скриптом/выполнимым файлом, который сработает в браузерах ваших пользователей. Защита: Проверять тип файла и не по расширению, а по внутреннему содержимому. Если это картинки то в браузеры к пользователям они должны попадать только в виде Скрипт загружающий файлы должен исключить наличие символов / и .. в именах файлов. Что бы через него нельзя было залить файл в произвольную папку на сервере Папка в которую заливаются файлы должна быть защищена от выполнения скриптов из нее. Для этого надо в .htaccess в этой папке (для apache) написать следующее: php_flag engine 0 RemoveHandler .php AddType "text/html" .php .cgi .pl .fcgi .fpl .phtml .shtml .php2 .php3 .php4 .php5 .asp .jsp Options -ExecCGI -Indexes

Ответ 2



Самое опасное, что может произойти - удаленное выполнение кода. Это означает, что злоумышленник может загрузить свой скрипт и запустить его. Что будет в скрипте зависит только от фантазии злоумышленника. Я вижу два способа, как убрать данную уязвимость: Проверять загружаемый файл. Если через Вашу форму будут загружать изображения, то необходимо проверить, является ли загружаемый файл изображением, и т.п. Убрать права на выполнение файлов. Таким образом злоумышленник сможет спокойно просматривать изображения, но при этом у него не будет возможности выполнить, например, php скрипт.

Обвертка над итератором для преобразования типа

#cpp #stl #boost #итераторы


Есть два типа A и B, между объектами этих типов установлено соответствие. Есть набор
X значений типа А и итератор по этому набору. Необходимо с минимальными трудозатратами
на основе итератора X получить итератор по значениям типа B.

В общем по-простому говоря, есть контейнер типа A, из итератора А нужно получить
итератор B, потому что клиент принимает итераторы B.

Например:

typedef std::pair A;
typedef float                 B;

B A2B(const A & item) // соответствие между A и B
{
    return item.second;
}

std::vector X;
input_iterator bi = magic_iterator_wrapper(A2B, X.begin());


Чем может быть magic_iterator_wrapper?
    


Ответы

Ответ 1



Можно использовать boost::transform_iterator #include #include #include #include using A = std::pair; using B = float; float A2B(const A & item) { return item.second; } template auto make_transform_iterator(I i, F f) { return boost::transform_iterator{i, f}; } int main() { std::vector
v = {{0, 1}, {0, 20}}; auto first = make_transform_iterator(v.begin(), A2B); auto last = make_transform_iterator(v.end(), A2B); std::cout << std::accumulate(first, last, 0) << '\n'; } >>> То же на реальном компиляторе <<<

Как растянуть по всей высоте несколько элементов, не изменяя их размера?

#android


У меня есть компоновка:



        

        

            


Ответы

Ответ 1



-Если вам надо сохранять позиционирование элементов относительно друг друга вам нужно использовать RalativeLayout -Второй способ, в корневой лейаут положить ещё 4 лейаута, всем им задать равный layout_weight. Дальше в каждый из них положить по 1 элементу(Button, TextView и т.д...) и сделать gravity по центру лайаута в который вложен элемент.

Ответ 2



Вставьте между ними пустые раздвигающие элементы TextView или Space (API level 14)

Как убрать кавычки в JSON?

#android #json #sqlite


У меня есть БД из нее получаю JSON следующим способом

    String DB_PATH = "/data/data/com.example.apps/databases/";
    String myPath = DB_PATH + DBHelper.DATABASE_NAME;// Set path to your database
    String myTable = DBHelper.TABLE_CONTACT;//Set name of your table
    SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    String searchQuery = "SELECT  * FROM " + myTable;
    Cursor cursor = myDataBase.rawQuery(searchQuery, null );

    JSONArray json = new JSONArray();
    cursor.moveToFirst();
    while (cursor.isAfterLast() == false) {
        int totalColumn = cursor.getColumnCount();
        JSONObject rowObject = new JSONObject();

        for(int i=0 ;  i< totalColumn ; i++) {
            if(cursor.getColumnName(i) != null) {
                try {
                    if(cursor.getString(i) != null) {
                        Log.d("TAG_NAME", cursor.getString(i));
                        rowObject.put(cursor.getColumnName(i), cursor.getString(i));
                    } else {
                        rowObject.put(cursor.getColumnName(i), "");
                    }
                }
                catch(Exception e) {
                    Log.d("TAG_NAME", e.getMessage());
                }
            }
        }
        json.put(rowObject);
        cursor.moveToNext();
    }
    cursor.close();
    Log.d("TAG_NAME_ALL", json.toString());
    return json.toString();


JSON получается какой необходим, за исключением одного значения latlng.

Я получаю - "latlng":"[54.601530521,55.918132215051]"

Нужно получить - "latlng":[54.601530521,55.918132215051]

Как избавиться от кавычек?
    


Ответы

Ответ 1



из комментарий и оригинал из stackoverflow.com Если вам нужно быстро перевести строку на double, хоть и с грязным кодом, тогда вы можете сделать так: String s = "[12.3456789,98.7654321]"; String trimmed = s.substring(1, s.length()-1); String[] parts = trimmed.split(","); double lat = Double.parseDouble(parts[0]); double lng = Double.parseDouble(parts[1]); Log.d("latlng", "lat="+lat+" lng="+lng); Это не красиво, но работает.

Predicate<T> и Func<string> в качестве T

#c_sharp #wpf


Есть List< Func< string>> нужно вызвать List.RemoveAll().Туда нужно передать Predicate<
T>. нужно удалить только определнные функции. На MSDN Видел пример с Point, но попытка
переделать аналогично под Func не получается. В чем проблема?

    List> _list;
    public MainWindow()
    {
        _list = new List>();
        _list.Add(this.test);
        _list.Add(this.test2);
        _list.Add(this.test);
        _list.Add(this.test2);
        _list.Add(this.test);

        Predicate> pre = ValidateFunc(test2,nameof(test2));// тут функция
и подчеркивается с ошибкой
    }

    private static bool ValidateFunc(Func obj,string targetName)
    {
        return targetName == nameof(obj);
    }

    string test()
    {
        textBox.Text += " 2";
        return "";
    }
    string test2()
    {
        textBox.Text += " 3";
        return "";
    }


Ошибка:Не удается неявно преобразовать тип "bool" в "System.Predicate< System.Func<
string>>"

Если как на MSDN без параметров то ошибка такая: Нет перегруженного метода для "ValidateFunc",
который соответствует делегату "Predicate< Func< string>>"
    


Ответы

Ответ 1



Я предлагаю такой вариант: Predicate> pre = item => item == this.test; В частности, при использовании этого предиката в качестве аргумента метода _list.RemoveAll, из коллекции _list будут удалены все вхождения метода test. Либо так, если вместо ссылки на метод вы желаете использовать строку с именем метода: Predicate> pre = item => item.Method.Name == "test"; А назначение вашего метода ValidateFunc мне понять не удалось. Вы в нем сравниваете строку targetName с nameof(obj) (то есть со строковой константой "obj").

Ответ 2



Ответ @DmitryD самый полезный для моего решения. То, чего необходимо было добиться выглядит так: List> _list; public MainWindow() { _list = new List>(); _list.Add(this.test); _list.Add(this.test2); _list.RemoveAll(getpredicate(test2)); } static public Predicate> getpredicate(Func obj) { Predicate> pre2 = item => item == obj; return pre2; }

Ответ 3



Во первых, ValidateFunc должен выглядеть следующим образом private static bool ValidateFunc(Func obj); Только один параметр. Во вторых, Вам @Etki сделал корректное замечание, Вы неправильно инициализируете свой Predicate> pre, Вы там вызываете Вашу функцию ValidateFunc, а надо так: Predicate> pre = new Predicate>(ValidateFunc); Ну и конечно, как нужно было код написать целиком: List> _list; public MainWindow() { _list = new List>(); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test); Predicate> pre = new Predicate>(ValidateFunc); _list.RemoveAll(pre); } private static bool ValidateFunc(Func obj) { return "test2" == obj.Method.Name; } string test() { textBox.Text += " 2"; return ""; } string test2() { textBox.Text += " 3"; return ""; } Ну и вариант решения с помощью лямбда функции: List> _list; public MainWindow() { _list = new List>(); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test); _list.RemoveAll(f => f.Method.Name == "test2"); } string test() { textBox.Text += " 2"; return ""; } string test2() { textBox.Text += " 3"; return ""; }

git pull accept theirs/ours

#git #git_merge #git_pull


Можно ли как-то заставить git во время pull-а использовать стратегию слияния theirs
для конкретной директории? Но если конфликты возникнут в других местах - пусть предоставить
мне возможность решать.

Сейчас в голову приходит только такое:
делаем hook, который отрабатывает после pull-а, и запускает git checkout --theirs
{моя директория}
    


Ответы

Ответ 1



на основе ответа: Simple tool to 'accept theirs' or 'accept mine' on a whole file using git для частичной автоматизации можно, например, использовать псевдонимы: $ git config --global alias.accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f" $ git config --global alias.accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f" и при возникновении конфликта после git pull для файлов/каталогов, которые должны быть ours, выполнить: $ git accept-ours -- файлы/каталоги ... а для тех, что должны быть theirs: $ git accept-theirs -- файлы/каталоги ...

Как реализовать заглушку метода поиска в базе данных для тестового контекста?

#c_sharp #net #entity_framework #юнит_тесты


Изолирую зависимости от реальной БД при написании модульных тестов в проекте. Интерфейс
репозитория имеет следующий вид:

public interface IRepository
{
   T Find(int id) where T: class;
}


В реальном контексте метод реализован следующим образом:

public ConcreteDBContext : DBContext, IRepository
{
//some code
   public T Find(int id) where T : class
   {
      return this.Set.Find(id);
   }
}


Вопрос: как правильно реализовать такой метод в FakeDBContext? И от чего наследовать
сам контекст, кроме самого интерфейса IRepository? 
    


Ответы

Ответ 1



Если в местах, где вы используете db context, зависимость имеет тип IRepository, то вам достаточно наследовать заглушку от этого интерфейса (для этого зависимости и интерфейсы и нужны :)). Как правило, для каждого теста вам нужна будет своя реализация метода Find. Поэтому правильнее говорить о моках. Самый правильный способ работать с моками -- использовать мок-фреймворки. Их великое множество: Moq, RhinoMock, NSubstitute и проч. Синтаксис их будет немного отличаться, однако суть работы с моками всегда одна: Создаем мок-объект. Устанавливаем, что должен возвращать нужный нам метод мок-объекта при вызове с такими-то параметрами. Проверяем, что нужный нам метод был вызван (опционально). Например, с использованием NSubstite это будет выглядеть так: var personId = 1; var repo = Substitute.For(); // для id = 1 возвращаем объект repo.Find(personId).Returns(new Person { Name = "John", LastName = "Doe" }); // для всех остальных id возвращаем null repo.Find(Arg.Is(a => a != 1)).Returns(null); var someObjectThatUsesRepo = new SomeObjectThatUsesRepo(repo); someObjectThatUsesRepo.SomeMethod(); // проверяем, что метод вызвался ровно один раз repo.Received(1).Find(personId);

Обработчик проваленного теста

#cpp #юнит_тесты


Производится юнит-тестирование usb-устройства (CDC). Тест открывает устройство, формирует
запрос, отправляет его устройству, проверяет ответ, закрывает устройство. В случае,
если тест провален, закрытие устройства не выполнится, и, следовательно, все последующие
тесты также будут провалены, так как не смогут открыть устройство. В связи с этим вопрос:
есть ли способ установить обработчик (handler, hook) проваленного теста, который бы
выполнял освобождение ресурсов, запрошенных тестирующей функцией?

Тесты создаются в Visual Studio, тип проекта c++ unit test.
    


Ответы

Ответ 1



В тестовых фреймворках всегда есть возможность указать код, который будет выполнять перед каждым тестом и после каждого теста. Этот код выполняется всегда, вне зависимости от результата теста. Соответственно в вашем сценарии можно сделать так: Код перед тестом открывает устройство. Выполняется тест. Код после теста закрывает устройство. В MSTest для этого используются атрибуты TestInitialize и TestCleanup. P.S. Только это у вас не юнит-тестирование, а интеграционное тестирование. В юнит-тестировании не используются сторонние зависимости.

Ответ 2



Ваши ответы подсказали мне, в какой области искать верный ответ. В Visual Studio в Native Unit test методы до и после тестирования объявляются следующим образом: TEST_METHOD_INITIALIZE(methodName) { // method initialization code } TEST_METHOD_CLEANUP(methodName) { // test method cleanup code } Внутри этих методов можно генерировать исключения и вызывать функции из статического класса Assert. Больше информации здесь: MSDN

SQL, cursor, перебор, добавляется две записи вместо одной

#sql_server #циклы #cursor


Пытаюсь с помощью курсора перебрать исходные данные и для каждой записи сделать те
или иные изменения. Вот сам запрос:

DECLARE @ID bigint --id attachments
DECLARE @personID BIGINT
DECLARE @territoryServiceID BIGINT
DECLARE @isAtClosed BIT

DECLARE @currentServerDate DATETIME = '2016-01-01 01:10:00.000' --this change GETDATE()
DECLARE @BeginDate DATETIME SET @BeginDate = @currentServerDate
DECLARE @periodYear INT SET @periodYear = DATEPART(YEAR,@currentServerDate) - 1

DECLARE cur cursor LOCAL STATIC
FOR
SELECT at.id, at.personID, at.territoryServiceID, ts.isClosing
FROM Attachments at
INNER JOIN Person p ON p.id = at.personID AND p.parentID IS NULL
INNER JOIN TerritoryServices ts ON ts.id = at.territoryServiceID
LEFT JOIN Attachments at2 ON at2.personID = at.personID AND at2.parentID = at.id
AND at2.attachmentStatusID IN (2,11,12)
WHERE at.attachmentStatusID = 1 AND at.causeOfAttachID = 8 AND at.endDate IS NOT NULL
AND at2.id IS NULL
AND p.id IN (15300000019296419,15300000018501113,15300000014988209,414674754,420940229,409531785)


OPEN cur

FETCH NEXT FROM cur INTO @ID, @personID, @territoryServiceID, @isAtClosed
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @personID_NVARCHAR NVARCHAR(MAX) SET @personID_NVARCHAR = CONVERT(NVARCHAR(MAX),@personID)
PRINT '1 ('+@personID_NVARCHAR+')'

IF (@isAtClosed = 1) -- if ter of CA is closing
    BEGIN
        -- Insert error into ErrorHandlingCampainOfAttach
        DECLARE @ErrorDescr NVARCHAR(MAX) SET @ErrorDescr = 'TerId: ' + CONVERT(NVARCHAR(MAX),@territoryServiceID)
        INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description])
        VALUES (@ID, @personID, @territoryServiceID, @periodYear, 1, GETDATE(), @ErrorDescr)
    END
ELSE
    BEGIN
        DECLARE @terAt2ID BIGINT
        DECLARE @isAt2Close BIT = 0
        SELECT @isAt2Close = ts.isClosing, @terAt2ID = ts.id FROM Attachments at 
        INNER JOIN TerritoryServices ts ON ts.id = at.territoryServiceID
        WHERE at.personID = @personID AND at.attachmentStatusID = 2 AND at.endDate
IS NULL

        IF (@isAt2Close = 1) -- if ter of attach is closing
            BEGIN 
                -- Insert error into ErrorHandlingCampainOfAttach
                DECLARE @ErrorDescr2 NVARCHAR(MAX) SET @ErrorDescr2 = 'TerAttachId:
' + CONVERT(NVARCHAR(MAX),@terAt2ID)
                INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description])
                VALUES (@ID, @personID, @territoryServiceID, @periodYear, 2, GETDATE(),
@ErrorDescr2)
            END
        ELSE
            BEGIN 
                BEGIN TRY
                BEGIN TRANSACTION TranName
                    -- Search active request
                    DECLARE @ID_zapros BIGINT 
                    SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID
AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID
                    IF (@ID_zapros IS NOT NULL) 
                        BEGIN
                            -- Canseled request

                            -- Block #1
                            -- Create cancel for active request
                            INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID,
                                causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID,
                                actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num)
                            SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID,
at.doctorID,
                                8,at.careAtHome,NULL,NULL, 11, @BeginDate, @BeginDate,
at.id, 
                                at.userID, at.registratorID, at.actualAttachmentID,
NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num
                            FROM Attachments at 
                            WHERE at.id = @ID_zapros

                            -- Set endDate for active request
                            UPDATE Attachments SET endDate = @BeginDate WHERE id
= @ID_zapros
                        END

                    --Search active attach
                    DECLARE @ID_prikrep BIGINT
                    SELECT @ID_prikrep = id FROM Attachments WHERE personID = @personID
AND endDate IS NULL AND attachmentStatusID = 2
                    IF (@ID_prikrep IS NOT NULL) 
                        BEGIN
                            -- Block #2
                            -- Insert detach
                            INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID,
                                causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID,
                                actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num)
                            SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID,
at.doctorID,
                                8,at.careAtHome,NULL,NULL, 8, @BeginDate, @BeginDate,
at.id, 
                                at.userID, at.registratorID, at.actualAttachmentID,
NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num
                            FROM Attachments at 
                            WHERE at.id = @ID_prikrep

                            --Set endDate for active attach
                            UPDATE Attachments SET endDate = @BeginDate WHERE id
= @ID_prikrep
                        END

                    -- Attach CA
                    INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID,
                        causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID,
                        actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num)
                    SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID,
at.doctorID,
                        8,at.careAtHome,NULL,NULL, 2, @BeginDate, NULL, at.id, 
                        at.userID, at.registratorID, at.actualAttachmentID, NULL,NULL,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num
                    FROM Attachments at 
                    WHERE at.id = @ID

                COMMIT TRANSACTION TranName

                END TRY
                BEGIN CATCH
                    ROLLBACK TRANSACTION TranName

                    -- Insert error into ErrorHandlingCampainOfAttach
                    INSERT INTO [dbo].[ErrorHandlingCampainOfAttach] ([AttachmentsID],[personID],[territoryServiceID],[periodYear],[reasonError],[addDate],[description])
                    VALUES (@ID, @personID, @territoryServiceID, @periodYear, 3,
GETDATE(),ERROR_MESSAGE())
                END CATCH
            END
    END

FETCH NEXT FROM cur INTO @ID, @personID, @territoryServiceID, @isAtClosed
END
CLOSE cur
DEALLOCATE cur


Запрос для курсора возвращает 6 строк(6 выбраны для примера), то есть все ID уникальные,
ничего не задваивается. Далее в зависимости от определенных условий производятся те
или иные действия, прошу обратить внимание на два блока действий (в комментариях называется
Block#1 и Block#2), именно они ведут себя странно. 

После выполнения запроса на какой-нибудь (тут тоже важно, не всегда на одной и той-же
записи, бывает то на одной то на другой, а то и на двух) записи задваиваются строки
с данными, то есть вставляется две строки у которых все данные кроме автоинкрементного
идентификатора повторяются! Причем если откатить действия и попробовать только на этой
записи на одной (то есть цикл прогнать для одной записи) все завершается отлично! Вот
такие-вот злые электрические силы. Непонятно почему так происходит, подскажите кто-нибудь
что не так, или в каком направлении искать решение? 

P.S. триггеров на вставку данных на таблице Attachments нету. Строки всегда вставляются
после всех действия, то есть допустим первое условие выполняется, вставляется строка
1, затем по второму условию вставляется строка 2, затем строка 3, и в случае если происходит
задвоение строки, то она вставляется самой последней, то есть после строки 3 вставляется
строка 4 идентичная строке 1 (или строке 2 когда как)
    


Ответы

Ответ 1



С помощью Mike удалось найти решение данной проблемы! Тут я изложу все поподробнее вдруг кому-то поможет. Итак, начнем. Результат запроса для курсора: ... как видно никакого дублирования идентификаторов нет С подсказкой Mike(спасибо огромное), в одно из полей (Node) записал id записи в переборе, в результате получил следующее: В первой записи все отлично, не будем ее рассматривать. Вторая запись по списку id = 14308060, personID = 414674754. В результате произошло задвоение (Block #1), но в поле Node видим, что в конце записался идентификатор следующей по порядку записи!!! Ниже приведен результат следующей записи: ... тут все нормально Далее.. Пятая запись id = 148362023, personID = 15300000018501113. В результате прошло задвоение (Block #2), опять же в поле Node идентификатор следующей записи Ниже результат следующей записи в которой все ровно: Итак, все это навело на мысль, значения в переменных остаются прежними если в результате установки возвращается NULL, хотя в каждом цикле переменная объявляется заново. Теперь смотрим что происходит: 1. Выполняется обработка второй записи, так как у нее есть активный запрос то следующее выражение: DECLARE @ID_zapros BIGINT SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID записывает в переменную @ID_zapros идентификатор 150118746, далее выполняется все как нужно, добавляется ровно столько записей сколько нужно, последней записи, которая дублируется еще пока нет! Далее выполняется обработка третьей записи. У данной записи активного запроса нет, поэтому следующее выражение возвращает NULL SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID но! в переменную @ID_zapros записывается не NULL(как я предполагал), а остается предыдущее значение! Вот тут то и зарыта собака. И получается что при обработке третьей записи добавляется еще одна запись в с данными о предыдущей записи... с 5 и 6 записью все тоже самое, только уже на другом этапе... Я думал что, так как переменная объявляется внутри цикла, то при каждом объявлении в нее будет записываться NULL, также ошибался что при установки переменной, если результат возвращает NULL, то и в переменную запишется NULL, оказалось совсем не так... Решение довольно простое, обнулять переменную принудительно, я сделал так: DECLARE @ID_zapros BIGINT SELECT @ID_zapros = id FROM Attachments WHERE personID = @personID AND endDate IS NULL AND attachmentStatusID != 2 AND id != @ID IF (@ID_zapros IS NOT NULL) BEGIN --Отказываем запрос --Создаем отказ активному запросу INSERT INTO Attachments (personID,orgHealthCareID,personAddressesID,territoryServiceID,attachmentProfileID,doctorID, causeOfAttachID,careAtHome,senderRequestID,senderSystemID,attachmentStatusID,beginDate,endDate,parentID,userID,registratorID, actualAttachmentID,ConflictAttachment,Node,regDate,isMigrated,isDuplicate,oldPersonID,servApplicationID,Num) SELECT at.personID,at.orgHealthCareID,at.personAddressesID,at.territoryServiceID,at.attachmentProfileID, at.doctorID, 8,at.careAtHome,NULL,NULL, 11, @BeginDate, @BeginDate, at.id, at.userID, at.registratorID, at.actualAttachmentID, NULL,@nvar_ID,at.regDate,NULL,0,at.oldPersonID,NULL,at.Num FROM Attachments at WHERE at.id = @ID_zapros --Закрываем дату активному запросу UPDATE Attachments SET endDate = @BeginDate WHERE id = @ID_zapros SET @ID_zapros = NULL END Извиняюсь за довольно большое изложения, но я впервые здесь, может что-то делаю не так вы уж простите! Еще раз спасибо всем кто откликнулся! Надеюсь это кому-нибудь поможет не напороться на те же грабли)

Ответ 2



Код не самый очевидный, не имея данных сложновато понять, что происходит. Как вариант, для отладки вы можете попробовать добавить output inserted.* для всех блоков insert, что даст вам возможность посмотреть в каком порядке и какие именно данные были вставлены. Пример работы output блока: declare @attachments table (id int, status_id int) insert into @attachments (id, status_id) output 'block #1', inserted.* values (1, 2) insert into @attachments (id, status_id) output 'block #2', inserted.* select 3, 8 Возможно, здесь: SELECT @ID_zapros = id FROM Attachments WHERE ... либо здесь SELECT @ID_prikrep = id FROM Attachments WHERE ... по мере движения курсора выбирается не то, что ожидается.

Самописный СМТП-сервер

#c_sharp #многопоточность #smtp


Я написал СМТП сервер, но работает он некорректно вот в каком моменте: 
если я 1 раз подключусь к нему через телнет, он ответит нормально (рис 1-2.), но
если я еще раз подключусь через другую консоль cmd, то я появится только черный экран
и все(рис3):


(рис 1)


(рис 2)


(рис 3)

В последнем случае что-бы я ни вводил, на экране ничего не отобразится, и даже не
залогируется моим СМТП

В первом же случае, мои команды отображаются в консоли, они логируюстя сервером и
я вижу в этой консоли ответ (рис 4):


(рис 4)

Т.е., что я вижу, один клиент к нему подключается, работает нормально сервер, во
всех остальных случаях он работает не корректно (верно?)

Вот как я реализовал СМТП-сервер (это win-сервис):

 protected override void OnStart(string[] args)
        {
SmtpHelper s = new SmtpHelper(this);
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(StartListen),
(object)s );
}

 void StartListen(object s)
        {
            try
            {
                var a = (SmtpHelper)s;
                a.Listen(); //запуск 
            }
            catch (Exception ex)
            {
                l.Write("Error (StartListen(object s)): " + ex.ToString());
                throw;
            }

        }




public void Listen()
        {
            try
            {
                SMTP_Listener = new TcpListener(IPAddress.Any, port); 
                SMTP_Listener.Start();

                while (true)
                {
                    clientSocket = SMTP_Listener.AcceptSocket();

                    _sessionId = clientSocket.GetHashCode().ToString();

                    _email.sessionId = Convert.ToInt32(_sessionId);


                    StartProcessing(newController);
                    l.Write("we are there");

                   // System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ClientThread),
SMTP_Listener.AcceptTcpClient());
                }

            }
            catch (Exception ex)
            {
                l.Write("SMTP Listen Error: " + ex.ToString());
                throw;
            }
        }



void StartProcessing(ClientSessionController newController)
        {

            try
            {
                m_ConnectedIp = ParseIP_from_EndPoint(clientSocket.RemoteEndPoint.ToString());
                m_ConnectedHostName = GetHostName(m_ConnectedIp);

                _email.ip = m_ConnectedIp;
                _email.port = 25;


                SendData("220 " + System.Net.Dns.GetHostName() + " Service ready\r\n");

                //if (!clientSocket.Connected)
                //    clientSocket.Connect(IPAddress.Any, port);

                //РАБОТА С ВХОДНЫМИ ДАННЫМИ
                while (true)
                {
                    //если есть данные, то считаем их
                    if (clientSocket.Available > 0)
                    {
                        //получение команды от клиента
                        string lastCmd = ReadLine();

                        //парсим команду от клиента (HELO, RCPT, DATA etc.)
                        if (lastCmd.Trim() != String.Empty)
                            ProceedCommand(lastCmd, newController);
                        //break;
                    }
                    else
                    {
                      //dump:  l.Write("[Socket isn't available now]");
                    }
                }               
            }
            catch (Exception ex)
            {
                throw;
            }

        }


ВОПРОС: 

Подскажите пожалуйста, как мне сделать так, чтобы мой сервис мог одинаково обслужить
всех подключаемых клиентов, а не только первого?
    


Ответы

Ответ 1



В подобных случаях обычно делают один поток слушатель, который прослушивает нужный порт. Когда подключается клиент создаётся новый поток для обслуживания непосредственно его и слушатель передаёт работу с клиентом этому потоку. При завершении клиентом работы с сервером этот поток уничтожается. Приблизительно как-то так.

TSQL, “простой некластеризованный индекс”

#sql #база_данных #sql_server


Есть несколько индексов такого вида:

CREATE INDEX IX_ProductVendor_VendorID ON Purchasing.ProductVendor (VendorID);


На MSDN здесь (в разделе "примеры", первый пример) сказано, что это "простой некластеризованный
индекс". Что это значит? Обычный первичный ключ? Может быть, глупый вопрос, но для
меня не очевидно, хотелось бы быть уверенным.
    


Ответы

Ответ 1



На Хабре есть аааааабалденная статья на тему индексов. Очень советую. Если вкратце, то: Индекс использует дерево для быстрого обращения к данным. У кластеризованного индекса в листьях дерева лежат сами строки данных. В силу природы дерева данные хранятся в уже отсортированном виде, поэтому кластеризованный индекс может быть только один. У некластеризованного индекса в листьях дерева лежат указатели на строки данных, т.е. для чтения данных необходима еще одна операция. Т.о. кластеризованных индексов у таблицы может быть несколько. Что это значит? Обычный первичный ключ? Понятие первичного ключа в общем-то не связано с индексом. В таблице может быть колонка, являющаяся первичным ключом, но без индекса. Однако на первичные ключи как правило создают кластеризованный индекс. В вашем вопросе VendorID это скорее просто foreign key -- на них обычно создают некластеризованные индексы.

C# полноэкранное приложение со своим разрешением

#c_sharp


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


Ответы

Ответ 1



По честному только через DirectX, но стоит учесть что он не любит внутри себя виндовые формочки.

Ответ 2



Для изменения разрешения существует функция ChangeDisplaySettings. Перечисляются режимы с помощью EnumDisplayDevices. Вы можете воспользоваться интеропом, чтобы вызвать эти функции в управляемом коде. Если вас интересуют игры, то у DirectX свои методы для изменения разрешения. В принципе ими можно пользоваться и по отдельности, если очень хочется.

Как управлять audio autoplay?

#php #javascript #html5 #аудио


У меня на сайте используется тег audio с autoplay. Как сделать чтобы autoplay срабатывал
только при первоначальной загрузке страницы, а при переходе обратно с внутренней или
при перезагрузке audio не повторялось?
    


Ответы

Ответ 1



'; }else{ setcookie('audio',1); echo ''; } ?>

Ответ 2



Можно сделать без php if(localStorage.getItem("Auth") != "yes"){ var audio = new Audio(); audio.src = 'sounds/music.mp3'; audio.autoplay = true; localStorage.setItem("Auth", "yes"); // запоминаем пользователя }

Как сохранить веб-страницу в формат mht программно?

#парсер


Решил заранее подготовить все ссылки страниц, а после сохранять их в формате .mht
Например, в .txt файле находятся все ссылки (каждая с новой строчки). Программа должна
читать оттуда ссылки и сохранять в формате .mht на жесткий диск.

Можно ли это реализовать программно и какую технологию лучше использовать?

Зачем мне это нужно?


  Есть один интернет-магазин. С него мне нужно скачать все изображения
  товаров. Пытался использовать jQuery через расширения Google Chrome.
  Пытался писать приложение на C#. Но, почему-то, загружаются не все
  картинки каталога.
  
  Вот, например эта страница: 
  www.onlinetrade.ru/catalogue/smartfoni-c13 Здесь показано 50 товаров.
  Ищу все конструкции "img". Скачиваю. В итоге, загружаются только
  первые 7 картинок товаров. В итоге, решил загрузить таким способом,
  описанным выше.

    


Ответы

Ответ 1



Точно ли сохраняет первые 7, а не 10 фото? Там на странице фильтр 10, 20, 50. Возможно ваш парсер просто не умеет наверное нажимать на цифру 50, для фильтра. А если 7, то возможно просто получалось что берет первую картинку и идет на следующую страницу. Там берет тоже первую и т.д. Соответственно, возможно вы просто чего-то не учли. Почему я так думаю? Потому, что урл спокойно себе парсится. Картинки (и не только) достаются без проблем. Вот пример с использованием php и Simple HTML DOM Parser (для использования Simple HTML DOM Parser конечно же надо его скачать...ресурс) // Добавлять сообщения обо всех ошибках, кроме E_WARNING error_reporting(E_ALL & ~E_WARNING); include './domParser/simple_html_dom.php'; class DomParser { public $url = ''; public $imgHost = ''; public $returnVal = 0; public function __construct($urlParse, $imgHostUrl) { $this->url = $urlParse; $this->imgHost = $imgHostUrl; } public function getImages($_data) { $i = 1; $data = $_data ? $_data : file_get_html($this->url); if ($data->innertext != '') { foreach ($data->find('div.catalog__displayedItem') as $a) { foreach ($a->find('.catalog__displayedItem__columnFoto img') as $img) { echo ''; $imgExt = explode('.', $img->src); // Это для добавления картинки себе в папку // Закоментировал в фиддле if ($image = file_get_contents($this->imgHost . $img->src)) { //file_put_contents('./images/' . $i . '.' . end($imgExt), $image); } } $i++; } echo '

'; $this->getNextPage($data, 'getImages'); $data->clear(); unset($data); } } public function getNextPage($data, $repeatFunctionName) { // сделал пока чтобы много циклов не делал не нагружал if ($this->returnVal >= 2) return; if ($data->innertext != '') { $this->returnVal++; foreach ($data->find('.catalogItemList__paginator a') as $a) { $str = iconv("windows-1251", "UTF-8", $a->title); if (mb_strpos(strtolower($str), 'ледующие', 0, 'UTF-8') !== false) { $page = explode('?', $a->href); $data_inner_link = file_get_html($this->url . '?' . end($page)); $this->$repeatFunctionName($data_inner_link); break; } } } } } $url = 'http://www.onlinetrade.ru/catalogue/smartfoni-c13/'; $imgHost = 'http://www.onlinetrade.ru'; $parser = new DomParser($url, $imgHost); $parser->getImages(null); /* $url = 'http://www.onlinetrade.ru/catalogue/smartfoni-c13/'; $imgHost = 'http://www.onlinetrade.ru'; $data = file_get_html($url); $i = 1; function getImages($data) { global $imgHost; global $i; if ($data->innertext!='') { foreach($data->find('div.catalog__displayedItem') as $a) { foreach ($a->find('.catalog__displayedItem__columnFoto img') as $img) { echo ''; $imgExt = explode('.', $img->src); // Это для добавления картинки себе в папку // Закоментировал в фиддле if ($image = file_get_contents($imgHost . $img->src)) { file_put_contents('./images/' . $i . '.' . end($imgExt), $image); } } $i++; } echo '

'; getNextPage($data); $data->clear(); unset($data); } } $return = 0; function getNextPage($data) { global $url; global $return; // сделал пока чтобы много циклов не делал не нагружал if ($return >= 2) return; if($data->innertext != ''){ $return++; foreach($data->find('.catalogItemList__paginator a') as $a){ $str = iconv("windows-1251", "UTF-8", $a->title); if (mb_strpos(strtolower($str), 'ледующие', 0, 'UTF-8') !== false) { $page = explode('?', $a->href); $data_inner_link = file_get_html($url . '?' . end($page)); getImages($data_inner_link); break; } } } } //getImages($data); */ Вариант использования класса и вариант обычный через функции (закоментированы ниже) Потрогать можно Здесь На данный момент специально установлено ограничение на парсинг только первых 3-х страниц (по 10 товаров), чтобы не грузить фиддл и закоменчена строка с file_put_contents потому что фиддл не пропускает, что логично))) вот пруф сохранения: И там еще много внизу... Как вариант можно и наверное лучше использовать (касаемо php) cURL cURL - свободная служебная программа командной строки, позволяющая взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL. Этот код просто скорее в целях показать, что всё работает, можно скачать и что у вас, скорее всего, где-то в коде ошибка. Не является, скорее всего, мой ответ ответом, но, возможно, этот код будет чем-то полезен и захотите как-то переделать под нужды. Нежели сохранять mht. Хотя памяти он будет кушать много.

Ответ 2



Для программного создания mht: C# source code for generating MHT files from an URL CDO.Message COM-объект, реализующий IMessage interface Из JavaScript попробуйте вызвать print(document.body.innerHTML); или document.execCommand('SaveAs','true','http://...')

Как запретить использовать приложение без интернета?

#java #android #android_sdk #безопасность


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

Есть ли универсальное решение?
    


Ответы

Ответ 1



Можно по разному: Проверять на входе в приложение наличие интернета, т.е. при запуске главного Activity. И не стартовать к-л задачи до успешной проверки. Сделать активити-проверщик интернета. Запускать на нынешнюю главную а эту. Если интернет есть, то запускать нынешнюю главную. Иначе - выходить из приложения. Обернуть все нынешние запросы в сеть в класс, проверяющий перед запуском задачи наличие инета. Если он есть - продолжаем, иначе - закрываем приложение. Проверить же наличие соединения с сетью (не факт, что там есть сам интернет) можно, согласно en-SO, так: public boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = cm.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); } Также надо добавить спец. разрешение в AndroidManifest.xml: Ещё момент: если надо проверять именно факт подключённости с интернету (а не подключено-или-подключается) то использовать надо netInfo.isConnected() вместо netInfo.isConnectedOrConnecting(). Проверить же есть ли интернет как таковой можно вот так: public boolean isInternetAvailable() { try { InetAddress ipAddr = InetAddress.getByName("google.com"); //можно заменить на к-л другой сайт if (ipAddr.equals("")) { return false; } else { return true; } } catch (Exception e) { return false; } } И не забываем про все нужные разрешения в манифесте:

Ответ 2



Исходя из описания вам однозначно нужно делать редизайн приложения и реализовывать запросы через отдельный класс который будет в том числе и обслуживать все ошибки сети. Для носимых устройств обычным делом является интернет, который может пропасть в любой момент и в любой момент появится опять, что нивелирует проверку соединения при старте приложения, т.к. оно может пропасть сразу же после проверки или же наоборот появится сразу после выхода из приложения.

Как подгружать табы из календаря?

#java #android


Мне нужно реализовать табы, в котором каждый отдельный таб это дата календаря. Табы
скроллятся вправо. Я так понимаю, что стандартный TabHost не поможет. Также наверняка
потребуется подгрузка/выгрузка элементов. Посоветуйте методы реализации и куда "копать". 


    


Ответы

Ответ 1



Здесь можно использовать горизонтальный список (ListView), адаптер которого будет формировать даты. Для отображения результата ниже самого горизонтального списка - фрагмент, в который по клику на айтеме списка будет отправляться информация, связанная с текущей позицией в списке.

Ответ 2



Я использую горизонтальный RecyclerView для этих целей, изначально допустим кладем в него на один месяц данные, ставим на на него ScrollListener, как только скроллим, допустим до dates.size() - 10, генерируем еще один месяц и добавляем в него.

Несколько параллельных потоков

#c_sharp #wpf #async #async_programming


Есть класс для обработки пула задач. 

public class PoolManager
{
    List>> _listFunc { get; set; }
    List _listName { get; set; }
    public bool Active { get; set; } = false;
    public PoolManager()
    {
        _listFunc = new List>>();
        _listName = new List();
    }

    public async Task StartPool()
    {
        if (!Active)
        {
            Active = true;
            while (Active)
            {
                if (_listFunc.Count != 0)
                {
                    await Task.Run(async () =>
                    {
                        var fun = _listFunc[0];
                        RemoveById(0);
                        await fun();

                    });
                }
            }
        }
       return "";
    }

    public void Add(Func> func,string name)
    {
        _listFunc.Add(new Func> (func));
        _listName.Add(name);
    }

    public void Stop()
    {
        Active = false;
    }
}


Всё работает, но есть необходимость запускать несколько паралельных таких пулов.
запускаю я его так:

 if (!VP[0].Active)
 {
      await Task.Run(async () =>
      {
           await VP[0].StartPool();
      });
 }
 else VP[0].Stop();


Но таким образом я могу запустить только 1 такой поток. Как можно реализовать одновременный
запуск нескольких таких потоков с возможностью в последствии обращаться к ним? И соответственно
без блокировки главного потока.
    


Ответы

Ответ 1



Создавать список Task'ов не нужно. Просто надо указать AttachedToParent Task.Factory.StartNew(() => { for(var i=0; i < 10; i++) Task.Factory.StartNew(() => { /*... */}, TaskCreationOptions.AttachedToParent); }).Wait(); Внешний Task дождется завершение всех Task'ов, запущенных в цикле. Если в основном потоке не надо ждать завершения внешнего Task, то Wait не надо указывать. Но при этом этот Task будет ждать завершение работы остальных, запущенных с AttachedToParent. Если требуется передавать данные, то надо использовать классы, например, из System.Collections.Concurrent. Пример - тут.

WP8.1 не работает кодировка windows-1251

#c_sharp #windows_phone_81


Необходимо из массива байт перевести текст в кодировке windows-1251 в строку.
Для этого я использую встроенное средство:

Encoding encoding = Encoding.GetEncoding("windows-1251");


Однако этот код выдаёт исключение:

'windows-1251' is not a supported encoding name.
Parameter name: name


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


Ответы

Ответ 1



Судя по всему System.Text.Encoding поддерживает всего три кодировки: System.Text.Encoding.BigEndianUnicode System.Text.Encoding.Unicode System.Text.Encoding.UTF8 Соответственно он не может найти windows-1251. Ибо такой кодировки он не знает. Чтобы использовать windows-1251 кодировку вам нужно реализовать свой класс, наследующийся от System.Text.Encoding и описывающий данную кодировку. Примерно так: public class Windows1251 : Encoding { static string alpha = "\0\a\b\t\n\v\f\r !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"; public override int GetByteCount(char[] chars, int index, int count) { return count; } public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { byte questionIndex = (byte)alpha.IndexOf('?'); for (int i = 0; i < charCount; i++) { int toIndex = byteIndex + i; int index = alpha.IndexOf(chars[charIndex + i]); if (index == -1) bytes[toIndex] = questionIndex; else bytes[toIndex] = (byte)index; } return charCount; } public override int GetCharCount(byte[] bytes, int index, int count) { return count; } public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { for (int i = 0; i < byteCount; i++) { chars[i + charIndex] = alpha[bytes[byteIndex + i]]; } return byteCount; } public override int GetMaxByteCount(int charCount) { return charCount; } public override int GetMaxCharCount(int byteCount) { return byteCount; } }

Ответ 2



С помощью сторонней библиотеки https://github.com/jstedfast/Portable.Text.Encoding легко получилось декодировать из кодировки windows-1251. Пример кода: var bytes = await response.Content.ReadAsByteArrayAsync(); Encoding encoding = Portable.Text.Encoding.GetEncoding(1251); var text = encoding.GetString(bytes, 0, bytes.Length);

Обращение к определенному в XAML словарю ресурсов из застраничного кода

#c_sharp #xaml


У меня есть словарь ресурсов,определенный в XAML-разметке,например так:

    
some text
text


Как обратиться к такому словарю из  застраничного кода на C#(например,добавить несколько
элементов)?
    


Ответы

Ответ 1



Все, уже разобрался. Необходимо создать Uri, который будет указывать на нужный словарь и присвоить его свойству Sourse нового словаря ресурсов: Uri uri = new Uri(@"sample.xaml"); ResourceDictionary dict = new ResourceDictionary(); dict.Source = uri;`

Как сохранить НЕ дефолтные данные в Settings.settings

#c_sharp


Как сохранить не дефолтные данные в файле Settings.settings?.Пробовал так

      private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
        // Добавьте здесь код для обработки события SettingsSaving.
        marker = WpfApplication16.MainWindow.getMarker();
        delay = WpfApplication16.MainWindow.getDelay();
        senderEmail = WpfApplication16.MainWindow.getCredentials()[0];
        recipientEmail = WpfApplication16.MainWindow.getCredentials()[1];
        subject = WpfApplication16.MainWindow.getCredentials()[2];
        text = WpfApplication16.MainWindow.getCredentials()[3];
        password = WpfApplication16.MainWindow.getCredentials()[4];
    }


,но при последующих запусках значения остаются дефолтными.При вызове Properties.Settings.Default.Save()
значения все равно затираются при перезапуске приложения.
    


Ответы

Ответ 1



Получите доступ к параметру и присвойте ему новое значение: Properties.Settings.Default.myColor = Color.AliceBlue; Если необходимо сохранять изменения параметров между сеансами приложения, вызовите метод Save, как показано ниже. Properties.Settings.Default.Save(); Официальное руководство тут

Удаление определенного количества байт с конца файла shell скрипт

#linux #shell


Добрый день. Собственно вопрос. Как средствами shell удалить с конца файла N - о
количество символов. 
Есть зашифрованный gpg файл. В конец его дописываем контрольную сумму. 
А затем ее нужно считать и удалить. Как?

пробовал средствами  sed но так и не дошел до рабочего варианта
    


Ответы

Ответ 1



Пусть в переменных n - длина контрольной суммы, file - имя файла. truncate -s $(( $(stat -c '%s' $file) - $n )) $file

Перетащить элемент из одного ListBox'a в другой

#c_sharp #wpf


Имеется 4 ListBox, из трех которых можно перетаскивать и кидать элементы в четвертый,
причем не перемещать, а копировать.
Как прописать события принимающему ListBox? события ListBox, из которых таскать,
прописал. из одного ListBox:


    
        
            
                
                
                  
                   
               
        
    



в этот:


        
            
             
        
    



для первого ListBox:

     private void helmet_MouseDown1(object sender, MouseButtonEventArgs  e)
    {
      _startPoint = e.GetPosition(null);


      }
    private void helmet_PreviewMouseMove(object sender, MouseEventArgs e)
   {
    if (e.LeftButton != MouseButtonState.Pressed) return;
    Point mousePos = e.GetPosition(null);
    Vector diff = startPoint - mousePos;
    if (Math.Abs(diff.X) <= SystemParameters.MinimumHorizontalDragDistance
     && Math.Abs(diff.Y) <= SystemParameters.MinimumVerticalDragDistance)
        return;
    var lst = sender as ListBox;
    var li = FindAnchestor((DependencyObject)e.OriginalSource);
    Console.WriteLine("move " + li);
    if (li == null) return;
    var str = lst.ItemContainerGenerator.ItemFromContainer(li);
    var data = new DataObject("txt", str);
    var res = DragDrop.DoDragDrop(li, data, DragDropEffects.All);
    if (res == DragDropEffects.Move)
        (lst.ItemsSource as IList).Remove(str);
     }
             static T FindAnchestor(DependencyObject current) where T :  DependencyObject
{
       do
    {
        if (current is T) return (T)current;
        current = VisualTreeHelper.GetParent(current);
    }
    while (current != null);
    return null;
}
     UPDATE  private void listHero_Drop(object sender, System.Windows.DragEventArgs e)
 {
           var o = e.Data.GetData("txt");
     var lst = sender as ListBox;
    (lst.ItemsSource as IList).Add(o);
     e.Effects = DragDropEffects.Move;
 }

     private void ListHero_OnDragEnter(object sender,    System.Windows.DragEventArgs e)
    {
         if (e.Data.GetDataPresent("txt"))
     e.Effects = DragDropEffects.Move;
 }`

    


Ответы

Ответ 1



как прописать события принимающему листбоксу? в xaml добавить Drop и DragEnter в cs добавить код обработчиков событий, примерно такой: void ListBox_Drop(object sender, DragEventArgs e) { var o = e.Data.GetData(...) as ...; ... e.Effects = DragDropEffects....; } void ListBox_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(...)) e.Effects = DragDropEffects....; } Код, который должен быть в обработчиках есть в примере тут. UPDATE: v1, перетаскивание строк -- заменил на следующий. UPDATE: v2, перетаскивания объектов разного типа. interface IData { } class Data1 : IData { public override string ToString() { return "Data1"; }} class Data2 : IData { public override string ToString() { return "Data2"; }} partial class MainWindow : Window { public MainWindow() { Items1 = new ObservableCollection() { new Data1(), new Data2() }; Items2 = new ObservableCollection(); this.DataContext = this; } public ObservableCollection Items1 { get; set; } public ObservableCollection Items2 { get; set; } Point startPoint; void DragList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { startPoint = e.GetPosition(null); } void DragList_PreviewMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed) return; Point mousePos = e.GetPosition(null); Vector diff = startPoint - mousePos; if (Math.Abs(diff.X) <= SystemParameters.MinimumHorizontalDragDistance && Math.Abs(diff.Y) <= SystemParameters.MinimumVerticalDragDistance) return; var lst = sender as ListBox; var li = FindAnchestor((DependencyObject)e.OriginalSource); Console.WriteLine("move " + li); if (li == null) return; var o = lst.ItemContainerGenerator.ItemFromContainer(li); var data = new DataObject(typeof(IData), o); var res = DragDrop.DoDragDrop(li, data, DragDropEffects.All); if (res == DragDropEffects.Move) (lst.ItemsSource as IList).Remove(o); } void ListBox_Drop(object sender, DragEventArgs e) { var o = e.Data.GetData(typeof(IData)); var lst = sender as ListBox; (lst.ItemsSource as IList).Add(o); e.Effects = DragDropEffects.Move; } void ListBox_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(typeof(IData))) e.Effects = DragDropEffects.Move; } static T FindAnchestor(DependencyObject current) where T : DependencyObject { do { if (current is T) return (T)current; current = VisualTreeHelper.GetParent(current); } while (current != null); return null; } }

Android. Фильтрация GPS данных, какую погрешность считать за норму?

#android #gps


Хотел найти пример приложения с удачного реализованным фильтром GPS-данных, скачал
два популярных трекера MyTracks, Open GPS Tracker. Первый разработали сами гугловцы. 
Запускаю, оба трекера выписывают кренделя и насчитывают киллометры, когда телефон
лежит на месте(за 20 минут первое приложение насчитало 2.5км второе 1.9км, третье без
фильтров 4.5км). Сервис Traccar на демо сервере без доп настроек 3.7 км. Да телефон
дешовый и GPS тоже, но все равно: 


Все на самом деле так плохо? Считать эту погрешность нормой или у
разработчиков были руки кривые?  
При движении на авто какую погрешность считать нормой?


P.S. Все очень относительно, но может найдется человек, который собаку съел на этом
деле и определился с нормами в построении маршрутов.
    


Ответы

Ответ 1



У разработчиков руки нормально. Только все телефоны по разному определяют координаты. И еще это зависит от погоды, здании где вы сидите и т.п. Так что если программа работает на улице нормально, это норма. Если на авто берите каждые 200 метров. Так лучше. И еще попробуйте фиксировать координаты при: каждые 200 метров если угол поворота авто больше 15 С если не движется фиксация каждую минуту. еще попробуйте программу от https://www.traccar.org/ Traccar (Server): git clone https://github.com/tananaev/traccar.git Traccar Client for Android: git clone https://github.com/tananaev/traccar-client-android.git Traccar Client for iOS: https://github.com/tananaev/traccar-client-ios.git

Удаление n символов из начала файла зашифрованого gpg используя Shell

#linux #shell


Стоит задача удаления n числа символов из начала файла используя shell. Файл зашифрован
gpg. Файл нельзя перезаписывать в другой файл.
    


Ответы

Ответ 1



dd if=$file of=$file skip=$n iflag=skip_bytes conv=notrunc Далее см. Удаление определенного количества байт с конца файла shell скрипт

Ответ 2



Для обрезания можно использовать cut. Например, для удаления первых 10 символов: cut -c 10- fname.txt > newfile.txt

Ответ 3



Инлайном можно попытаться так: sed -i '1s/^.\{10\}//' fname.txt но валидно только для текстовых файлов.

Как в Javascript узнать полную высоту страницы document.documentElement?

#javascript #html


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


Ответы

Ответ 1



https://stackoverflow.com/a/1147768/873481 var body = document.body, html = document.documentElement; var height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight );

Передача логов по сети

#java #веб_программирование #логирование


Есть ли готовая реализация для передачи логов из java веб приложения по сети на другой
сервер? Или это делается как обычная передача файлов через сокет? В смысле, может быть
есть уже какая-то готовая библиотека для этого? 
    


Ответы

Ответ 1



Зависит от того, чем вы пользуетесь для логирования. Для Logback, например, существуют SocketAppender и SSLSocketAppender для отправки событий по сети, SyslogAppender для отправки на Syslog-сервер. Сервер для логирования через SocketAppender настраивается обычными средствами (XML) и запускается просто из командной строки: java ch.qos.logback.classic.net.SimpleSocketServer 6000 \ src/main/java/chapters/appenders/socket/server1.xml В Log4j 2 реализованы JMSAppender / KafkaAppender / ZeroMQ Appender для прокачки логов через очереди и аналогичные упомянутым выше SocketAppender и SyslogAppender.

Сохранение данных в CSV файл

#java #android #csv


после сохранения в файл при открытии с excel кодировка бывает не понятной(только
если текст на русском), а через notepad++ все читабельно, в чем проблема подскажите
пожалуйста

String filename = "mytest.csv";
String entry = "Задача" +";"+"первая";
try {
    FileOutputStream out = openFileOutput(filename, Context.MODE_APPEND);
    out.write(entry.getBytes());
    out.close();

} catch (Exception e) {
    e.printStackTrace();
}


и если не сложно подскажите что почитать для создания csv файла в android
    


Ответы

Ответ 1



Попробуйте или в файл сохранять в нужной кодировке: // Строка Unicode String string = "..."; // Записываем строку в текстовый файл в кодировке Cp866 PrintWriter pw = new PrintWriter // класс с методами записи строк (new OutputStreamWriter // класс-преобразователь (new FileOutputStream // класс записи байтов в файл ("file.txt"), "Cp866"); pw.println(string); // записываем строку в файл pw.close(); или, например, строку сразу записывать в нужной кодировке // Строка Unicode String string = "..."; // Записываем строку в текстовый файл в двух кодировках (Cp866 и Cp1251) OutputStream os = new FileOutputStream("file.txt"); // класс записи байтов в файл // Записываем строку в кодировке Cp866 os.write( string.getBytes("Cp866") ); // Записываем строку в кодировке Cp1251 os.write( string.getBytes("Cp1251") ); os.close(); Если файл у вас уже существует, можно сделать проверку в самом начале и удалить его: File f = new File("1.txt"); if (f.exists()) f.delete();

Rails - yml файл для всех языков

#ruby_on_rails #локализация #yml


Я переводил свое Rails-приложение и столкнулся со следуюшей проблемой. Не все элементы
надо переводить. Например, в en.yml у меня хранятся не только фразы, но и ссылки. Переводить
их не имеет смысла, но если их не включасть, например, в ru.yml, то будет ошибка translation_missing. 

@MichaelRadionov посоветовал использовать наследование. 

Соответственно, вопрос: Как использовать наследование в YML файлах
    


Ответы

Ответ 1



Использовать наследование не нужно. Эта функция уже включена в гем rails-i18n. Для того что-бы все работало, нужно отредактировать файл application.rb: # Автозагрузка всех языковых файлов config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # Дефолтовый язык config.i18n.default_locale = :ru # Возврат к английскому при ошибках config.i18n.fallbacks = [:en] # Так же можно указывать какой язык использовать при ошибках config.i18n.fallbacks = {'ru' => 'en'}

Как реализовать ограниченный лог?

#java


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

MyLog log = new Mylog(1024); // создание лога размером в 1024 записи
log.add("запись в логе #1"); // добавляем запись
log.add("запись в логе #2"); // ещё добавляем запись
...
log.add("запись в логе #1025); // запись #1 затирается все строки сдвигаются и запись
#1025 становится в конец
String[] arr = log.toArray(); // Возвращает массив из 1024 строк


Как такое оптимальнее всего сделать?  

Возможно есть какое-то название для этого "лога", разновидность стека какая нибудь там?  

Сложность вставки в худшей случае будет O(n) или еще больше?  

И да, возможно есть это в стандартной библиотеке?
    


Ответы

Ответ 1



Думаю можно сделать таким образом: MyLog log = new Mylog(1024); - создается массив из 1024 элемента Курсор при создании = 0 this.cursor = 0; this.perepolneniye = FASLE; функция Add() добавляет запись и передвигает курсор public void add(String logData){ this.cursor ++; if (this.cursor > MAX_SIZE) { this.cursor = 0; this.perepolneniye = TRUE; } logArray[this.cursor] = logData; } Теперь когда нужно все это собрать и распечатать, нужно с начало собрать из cursor + 1 до конца и потом из начало до cursor'а. Но если не было переполнения, тогда только с начало до cursor'а. public void outResult(){ String result = ""; if (this.perepolneniye) { // Собираем от this.cursor+1 до MAX_SIZE } // Собираем от 0 до this.cursor return result; }

Ответ 2



Возможно вам подойдет тип данных очередь (разновидность списка), с той оговоркой, что при добавлении элемента будет проверяться длина очереди и, если надо, последний элемент будет выталкиваться. Сложность вставки будет О(1), но вот получение и изменение n-го элемента будет O(n). В джава нет встроенного типа данных очередь, но есть LinkedList, на основе которого можно легко сделать соответствующий класс: class Log { public int max_log_length; //максимальная длина public LinkedList list; //собственно список элементов public Log(int len) { this.list = new LinkedList(); this.max_log_length = len; } public void addFirst(T t) { this.list.addFirst(t); if (this.list.size() > this.max_log_length) { this.list.removeLast(); } } public T get(int index) { return this.list.get(index); } public void set(int index, T t) { this.list.set(index, t); } } Использовать соответственно так: Log log = new Log(1024); Получить из него массив можно так: String[] log_array = log.list.toArray(new String[b.max_log_length]); Естественно надо еще добавить различные проверки на выход за границы списка и много чего другого.

Локализация php

#php


Делал локализацию, получилось все очень громоздко.

Как это исправить?

if(isset($_GET['lang'])) {

    if ($_GET['lang'] === "ru") $lang = "ru";   

    elseif ($_GET['lang'] === "ua") $lang = "ua";

    else $lang = "en";

    setcookie("lang", $lang, time()+30758400, "/");

} else {
       if (empty($_COOKIE['lang'])) {

            $b_lang = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);

            if ($b_lang == "ru") $lang = "ru";

            elseif ($b_lang == "uk") $lang = "ua";

            else $lang = "en";

        }

        else {

            if ($_COOKIE['lang'] === "ru") $lang = "ru";    

            elseif ($_COOKIE['lang'] === "ua") $lang = "ua";

            else $lang = "en";

        }
}

if ($lang === "ru") include("lang/ru.php");

elseif ($lang === "ua") include("lang/ua.php");

else include("lang/en.php");

    


Ответы

Ответ 1



$allowedLang=array("ru","ua","en"); $needCookie=false; if(isset($_GET['lang'])) { $lang=$_GET['lang']; $needCookie=true; } elseif(empty($_COOKIE['lang'])) $lang=substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2); else $lang=$_COOKIE['lang']; if(in_array($lang,$allowedLang)) $lang='en'; if($needCookie) setcookie("lang", $lang, time()+30758400, "/"); include("lang/$lang.php"); Ну и совсем хардкорный:

Ответ 2



Больше вариантов :) function resolveLanguage() { // эти значения стоит хранить где-то в конфиге // чтобы потом не надо было менять код $allowedLanguages = array('ru', 'ua', 'en'); $defaultLanguage = 'en'; // порядок имеет значение // можно добавить еще какой-то источник для определения языка $preferredLanguages = array( isset($_GET['lang']) ? $_GET['lang'] : null, isset($_COOKIE['lang']) ? $_COOKIE['lang']: null, substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2), ); // убираем лишние, хотя смысла в этом нет - можно убрать (см. ниже) $preferredLanguages = array_filter($preferredLanguages); // выбираем первый разрешенный язык foreach ($preferredLanguages as $language) { if (in_array($language, $allowedLanguages)) { return $language; } } // если ничего не нашли.. return $defaultLanguage; } function saveLanguage($language) { setcookie("lang", $language, time()+30758400, "/"); } Использование: $language = resolveLanguage(); include("lang/{$language}.php"); saveLanguage($language); // ну не знаю, почему после, вдруг на include всё сдохло :) Делать код коротким неправильно (в данном случае). Он должен быть понятным и легко обновляемым/настраиваемым. upd. В php 7.0 можно написать так: $preferredLanguages = array( $_GET['lang'] ?? null, $_COOKIE['lang'] ?? null, substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2), );

Yii2 CacheSession создает сессию в $_SESSION и в кеше одновременно

#php #yii2


Случайно заметил такой нюанс при использования хранилища сессий в кеше ( в моем случае
memcached ) Yii2 создает одновременно ее же и в массиве $_SESSION, хотя по логике не
должен его использовать если в настройках указывается другое хранилище

Конфиг: ( пример - http://www.yiiframework.com/doc-2.0/yii-web-cachesession.html )

'cache' => [
        'class' => 'yii\caching\MemCache',
        'useMemcached' => TRUE,
        'servers' => [
            [   
               'host' => '******/.system/memcache/socket',
               'port' => 11211,
               'weight' => 64,
           ],

       ]
    ],
    'session' => [
        'class' => 'yii\web\CacheSession',
       // 'cache' => 'cache',
    ],


Создание сессии:

    $session = Yii::$app->session;
    $userDataStorage = [
        'id'        => $this->id,
        'name'      => $this->name,
        'settings'  => json_decode($this->settings),          
    ];
    $session->set('user_data' , $userDataStorage);


Проверяем:

        echo 'Yii session -> ';
            var_dump(Yii::$app->session->get('user_data')  );
            echo '------------- 
'; echo 'Php session -> '; var_dump($_SESSION); echo '-------------
'; var_dump(ini_get('session.save_path')); Видим: Yii session -> array(4) { ["id"]=> int(1) ["name"]=> string(5) "admin" ["settings"]=> NULL } ------------- Php session -> array(3) { ["__flash"]=> array(0) { } ["__id"]=> int(1) ["user_data"]=> array(4) { ["id"]=> int(1) ["name"]=> string(5) "admin" ["settings"]=> NULL } } ------------- string(24) "****/.system/tmp" Собственно это баг или... ? В чем тогда смысль настройки хранения сессий в кеше если он дублируется со стандартным ? Или я что-то делаю не так? СОРРИ не доглядел. https://github.com/yiisoft/yii2/blob/master/framework/web/Session.php методом registerSessionHandler() устанавливает session_set_save_handler а класс "CacheSession" реализует методы которые будут хранить сессию в кеше определенном в настройках, т.о. $_SESSION хранится уже не в файле папки tmp (как по умолчанию) а в memcached. Вопрос закрыт.


Ответы

Ответ 1



Возможно будет кому-то полезно, тогда начну сначала. Как настроить кеширование Yii2 для работы с memcache или memcached ( в чем отличия я думаю тут описывать нет смысла, в нете масса инфы по этому поводу ), постараюсь кратко изложить саму суть. Итак, для начала заходим в файл конфигурации проэкта и добавляем настройки кеширования и подключения к серверу 'components' => [ ... 'cache' => [ 'class' => 'yii\caching\MemCache', 'useMemcached' => TRUE, 'servers' => [ [ 'host' => 'localhost', 'port' => 11211, 'weight' => 64, ], ] ], ... ] Параметр 'useMemcached' ( класс MemCache расположен в директории yii2/caching/MemCache.php ( наследуется от компонента Cache /yii2/caching/Cache.php ) и по умолчанию FALSE, т.е. юзает memcache ) указывает на то что будет использоватся memcache или memcached, для использования memcached ставим в конфиге 'useMemcached' => TRUE Далее если все верно настроено прописано можем юзать кеш \Yii::$app->cache->set('key', 'value'); \Yii::$app->cache->get('key'); //или можем кешировать запросы в БД $db = Yii::$app->db; $result = $db->cache(function ($db) { return $db->createCommand('SELECT * FROM tablename LIMIT 0,1000')->queryAll(); }); // и т.д. **** Подробнее в доке http://www.yiiframework.com/doc-2.0/guide-caching-data.html Тут сразу нужно оговорится если вы захотите проверить работу Yii2 memcached напрямую, т.е. в Yii2 \Yii::$app->cache->set('mykey', 'value'); в произвольном файле $m = new Memcached(); $m->addServer('localhost', 11211); var_dump($m->get('mykey')); У вас ничего не получится т.к. компонент Cache Yii ( /yii2/caching/Cache.php ) методом buildKey так сказать "нормализует" ключи ( описание метода есть в классе ), но можно для теста сделать так в Yii2 $cache = Yii::$app->cache; $keyStr = 'cache_test'; $key = $cache->buildKey($keyStr); $cache->set($keyStr, 'This is mem test!'); $get = $cache->get($keyStr); var_dump($get , $key); // дампим результат из кеша и сгенерированный ключ ( копируем его ) в произвольном файле $m = new Memcached(); $m->addServer('localhost', 11211); $result = $m->get('242c9254b0a4b5ea5c7f0e000f668408'); // Вставляем полученый ключ var_dump(unserialize($result)); Далее собственно ближе к сути, мы хотим хранить сесии в нашем мемкеше, для этого идем обратно в конфиг и добавляем после настроек кеша следующее 'session' => [ 'class' => 'yii\web\CacheSession', //'cache' => 'cache', ], Теперь для работы с сессией будет заюзан класс CacheSession ( /yii2/web/CacheSession.php наследуется от Session /yii2/web/Session.php ) и можно создать нашу сессию \Yii::$app->session->set('Mysession', 'Mem session'); И собственно тут у меня возник некий конфуз, ибо \Yii::$app->session->get('Mysession'); // Вернет нам значение сессии $_SESSION // К моему удивлению так же содержал в себе эту сессию Но на самом деле ничего страшного здесь нет, $_SESSION уже не хранится на сервере в папке tmp как по умолчанию, теперь $_SESSION хранится в мемкешед. Все дело в том что класс CacheSession переопределяет некоторые методы класса Session ( в подробности работы вдаватся не буду, можно впринципе пройтись по этим файлам и посмотреть ) в т.ч. getUseCustomStorage(), так же класс Session имеет метод registerSessionHandler() который вызывается при откритии сессии, метод open(), в Session и вызывает в этом случаи getUseCustomStorage() который был переопределен, собственно после этого и происходит магия переноса $_SESSION в мемкешед, функция session_set_save_handler() ( http://php.net/manual/ru/function.session-set-save-handler.php ) переопределит методы работы с сессией на пользовательские. После этого если мы сделаем так $_SESSION['mysession'] = 'value' ( так же как и в методе Session set() ), после открытия сесиии медодом Session open(), сессия будет хранится в нашем кеше. Надеюсь мои изысканя будут кому-то полезными

Что делать, если удалил файл, принадлежащий пакету?

#linux #ubuntu #debian


Ненароком удалил файл /usr/bin/env, и теперь даже команда vagrant up выдает ошибку:


  bash: /usr/bin/vagrant: /usr/bin/env: плохой интерпретатор: Нет такого файла или
каталога


Как его вернуть?
    


Ответы

Ответ 1



узнать, какому пакету принадлежит файл, можно так (приведён и типичный ответ): $ dpkg -S /путь/к/файлу название-пакета: /путь/к/файлу переустановить пакет можно так: $ sudo apt-get install --reinstall название-пакета

Big data, оптимизация запросов

#sql_server #big_data


Есть следующая простая структура данных

Id; fk_Security_Id; DateTime; Price


Строка хранит данные по инструменту(активу), дату и время, цену(котировку). Строк
в БД на данный момент ~ 1 млрд. 200 млн. (10 инструментов с историей за прошлые 10 лет)

Задача - выборка данных по указанному fk_Security_Id и промежутку DateTime(например,
июль 2000г.) за адекватный промежуток времени (в идеале меньше минуты).

Сначала, я использовал знакомый мне MSSQL и навесил в лоб clustered index на эти
2 поля. В результате поиск по этим 2 полям занимает в районе 35 минут и сожранные 6.5Gb
RAM. Не совсем то, что конечно хотелось бы.
Какие варианты решения вижу пока я:


Не менять выбранную бд, а изменить саму структуру хранения
данных. Например разнести в разные таблицы данные по разным инструментам. В
этом случае конечно будут абсолютно идентичные таблицы с точки
зрения структуры, но можно будет выиграть некоторое время на поиске и
дальнейшее добавление новых инструментов не будет влиять на то самое время поиска.
И тогда вместо композитного кластерного индекса, индекс
будет состоять из одного поля - datetime. Также возможно здесь
имеет смысл вместо поля datetime в качестве индекса брать некий
timestamp или преобразованный Id. Но не уверен что это даст
существенный прирост в поиске, хотя стоит попробовать думаю.
Использовать какую-нибудь более легковесную бд, например postgres (дружит с необходимым
мне EF, что очень хотелось бы) + есть нативная поддержка Sphinx-а например.
Использовать какое-нибудь NoSql решение. С данными бд дел не имел, но допускаю,что
в моем случае данные укладываются в простую структуру key-value. Правда, наверное те
NoSql которые держат данные в RAM мне не подойдут потому что у меня просто столько
памяти нету. Хотя, если я не ошибась есть и достаточно шустрые дисковые NoSql , Aerospike
например. Но опять же поскольку я с ними не работал я не могу оценить насколько они
дадут выигрыш по времени по сравнению с обыными реляционными бд.


База не распределенная, ресурсы машины - 8 потоков и 8Gb RAM. Буду рад любому совету.
    


Ответы

Ответ 1



Пара мыслей (eсли вы всё же остановитесь на MSSQL). На мой взгляд big-data подразумевает щепетильное отношение к структурам хранения данных и типам хранимых данных. Сравните, к примеру, размеры различных типов данных для хранения дат и чисел: declare @dt datetime = getdate(), @dt2 datetime2(0) = getdate(), @sdt smalldatetime = getdate(), @m money = 1.0, @f float = 1.0, @dec_15_5 decimal(15,5) = 1.0, @r real = 1.0 select [datetime] = datalength(@dt), [datetime2(0)] = datalength(@dt2), [smalldatetime] = datalength(@sdt), [money] = datalength(@m), [float] = datalength(@f), [decimal(15,5)] = datalength(@dec_15_5), [real] = datalength(@r) datetime datetime2(0) smalldatetime money float decimal(15,5) real --------- ------------- -------------- ------ ------ -------------- ----- 8 6 4 8 8 5 4 Если тип столбца DateTime у вас datetime, рассмотрите возможность использования, например, типа smalldatetime (диапазон значений от 1900-01-01 до 2079-06-06 с точностью 1 минута). Если, тип стоблца Price, к примеру, float - рассмотрите возможность использования типов decimal (numeric) или real. Чем меньше размер строки данных, тем больше строк помещается в одну страницу памяти, соответственно легче оперировать ими в запросах. В таблицах с большим числом строк нелишним будет избегать NULL-able столбцов (это также сэкономит немного места). Правда следствием компактного хранения может быть некоторое неудобство в написании запросов, когда, например, при вычислении среднего для сохранения точности приходится делать кастинг в тип с большей точностью, а потом обратно. Да и сам кастинг несколько повысит стоимость запроса. Ваша идея разнести инструменты по таблицам имеет рациональное зерно. Нужно ли их держать в одной таблице, и в самом ли деле нужен Id в таблице, если, к примеру, на неё нет ссылок - решать вам. Однако если разнести данные по таблицам вида create table SomeInstrument ( DateTime smalldatetime not NULL primary key, Rate real not NULL ) то общий объём хранимых данных явно уменьшится, т.к. не будет столбцов Id и fk_Security_Id. Если всё же оставите всё в одной таблице, то fk_Security_Id (вместе с primary key таблицы, на которую он ссылается) имеет смысл перевести на тип tinyint, раз уж инструментов всего около десятка.

Запуск и остановка служб в Linux Mint

#linux #service


Какими командами останавливаются/запускаются службы в Linux Mint?

P.S. Разобрался:

sudo /etc/init.d/name_service stop/start

    


Ответы

Ответ 1



Бо́льшую часть служб можно запустить/перезапустить/остановить командой service SERVICE_NAME start/restart/stop Но некоторые такому управлению не поддаются и нужно использовать другие команды: /etc/init.d/SERVICE_NAME start/restart/stop Естественно, что это придётся выполнять с правами root.

Запуск сервера Gunicorn в Django

#python #django #gunicorn


В доках : $ gunicorn myproject.wsgi
Не могу понять где в моем приложении объект *.wsgi и должен ли быть по дефолту?
    


Ответы

Ответ 1



Да, он есть по дефолту.Он лежит в папке с названием проекта, где находится settings.py. Собственно в примере его и вызывают из этой папки, нужно заменить myproject на имя вашего проекта. . └── test_for_stack ├── manage.py └── test_for_stack ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py <-- Вот он

Ответ 2



myproject.wsgi это название модуля, который содержит application объект (входная точка для WSGI приложения). Ищется он также как и любой другой модуль в Питоне (представьте что происходит во время import myproject.wsgi). В случае django, если вы запустите эту команду из той же директории, где ваш manage.py находится, то PYTHONPATH будет содержать myproject пакет из текущей рабочей директории автоматически (как это обычно бывает когда вы любой Питон скрипт запускаете). Вместо myproject вы должны своё имя проекта указать (имя которое вы использовали в startproject команде): $ django-admin startproject your_project $ tree your_project your_project ├── manage.py └── your_project ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py $ cd your_project your_project$ gunicorn your_project.wsgi

node-sass не устанавливается

#nodejs #sass #webpack


Несмотря на все ухищрения не устанавливается node-sass. sass-loader для webpack установился
нормально (есть в package.json), а модуль node-sass устанавливается (видно появляется
соответствующая папка в  node-modules, IDE Sublime Text), потом выдается ошибка и папка
исчезает.

Ошибка такая 

failed at the node-sass@3.4.2 postinstall
node scripts/build.js

Exit status 3221225477


Я все перепробовала: создавала карту в webpack.config.js

{
  test: /\.scss$/,
  loader: 'style!css!sass?sourceMap'
}


В loader.js заменила строчку 

if(map && typeof map !== "string") {
    map = JSON.stringify(map);
    }


Ничего не работает! Или на windows XP в принципе не устанавливается этот модуль (
хотя все остальные модули справно работают)?
    


Ответы

Ответ 1



Вот и нашла ответ на свой вопрос. На XP есть проблема со входом в библиотеку msvcrt.dll для Ruby. Хотя похожие проблемы с установкой node-sass есть и на 10 версии OS. На старых версиях проблема решается установкой своей среды разработки. Подробности здесь: https://github.com/oneclick/rubyinstaller/issues/239 https://github.com/oneclick/rubyinstaller/wiki/Development-Kit#building-the-devkit https://github.com/oneclick/rubyinstaller/

Как получить данные из 2 элемента Json?

#android #json


{
    "status":"success",
    "data":{
       "215":{},
       "248":{},
       "252":{}
    }
}


Как получить 2 элемент?

json.getJsonObject("data"). А дальше что? Тут проблема в том, что я по сути не знаю
названия объектов. Таких как 215, 248, 252. На то он и запрос, как быть?
    


Ответы

Ответ 1



Что есть второй элемент не совсем понятно, у объектов порядок свойств может быть произвольным. А получить все ключи можно так: JsonObject data = json.getJsonObject("data"); Set> entries = data.entrySet(); for (Map.Entry entry: entries) { System.out.println(entry.getKey());//"215","248","252" } ...и, например, взять второй элемент. А вообще, логичным выглядел бы json вида: { "status":"success", "data":[ {"id":"215","object":{}}, {"id":"248", "object":{}}, {"id":"252", "object":{}} ] } или id внутри object: { "status":"success", "data":[ {"id":"215",...}, {"id":"248",...}, {"id":"252",...} ] }

Ответ 2



Опишите класс получаемого объекта и дессериализуйте его: gson.fromJson(jsonString, Type.class);

Ответ 3



В вашем случае доступ можно получить только по ключу, т.к. тип у data - JsonObject, а не JsonArray.

Как отключить отображение кнопки назад (DisplayHomeAsUpEnabled) в главном активити?

#android #activity #android_fragment


Есть активити и фрагмент в фрагменте стоит DisplayHomeAsUpEnabled. При переходе с
активити в фрагмент кнопка назад появляется все хорошо, но при нажатии и перехода назад
в активити стрелочка остается отображаеться? Как убрать?

Пробывал не помогло:

getSupportActionBar().setHomeButtonEnabled(false);

getSupportActionBar().setDisplayHomeAsUpEnabled(false);

getSupportActionBar().setHomeAsUpIndicator(null);


Код кнопки в фрагменте DisplayHomeAsUpEnabled:

@Override
    public void onResume()
    {
        super.onResume();
        ((ActionBarActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }


Код активити:

public class MainActivity extends ActionBarActivity implements ExpandableListView.OnChildClickListener,
View.OnClickListener {
    private static FragmentManager mManager;
    Button button1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        button1 = (Button) findViewById(R.id.button1);
        mManager = getSupportFragmentManager();

        getSupportActionBar().setIcon(R.drawable.ic_launcher);

        getSupportActionBar().setDisplayHomeAsUpEnabled(false);

       /* FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });*/

       // button1.setOnClickListener(this);
            button1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Fragment fragment = null;


                mManager.findFragmentById(R.id.fragmentContainer);
                    if (fragment == null) {
                        fragment = new sovety_Fragment();
                        mManager.beginTransaction()
                                .add(R.id.fragmentContainer, fragment)
                                .replace(R.id.fragmentContainer, fragment)
                                .addToBackStack(null)
                                .commit();
                    }

            }


    });
    }



    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
        if (id == android.R.id.home) { onBackPressed(); return true; }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {

        return false;
    }

    @Override
    public void onClick(View v) {

    }
}

    


Ответы

Ответ 1



Вы вызываете код, убирающий стрелку до того, как её показываете. Т.к. вы убираете фрагмент нажатием кнопки "назад" именно в слушателе её нажатия надо убирать стрелку. Засим попробуйте добавить обработчик нажатия кнопки назад в активити и именно в нём убрать стрелку: @Override onBackPressed() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); super.onBackPressed(); }

Ответ 2



Вы вызываете getSupportActionBar().setDisplayHomeAsUpEnabled(false); (прячете кнопку назад) при создании активити, затем добавляете на активити фрагмент, в котором показываете эту кнопку, но вы не прячете её снова при удалении фрагмента. Так с чего бы она должна пропасть. Добавьте вот такой метод в активити: public void onBackPressed() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { getSupportActionBar().setDisplayHomeAsUpEnabled(getSupportFragmentManager().getBackStackEntryCount() > 1); getSupportFragmentManager().popBackStack(); } else { super.onBackPressed(); } }