Текущее время: Пт, июл 18 2025, 12:23

Часовой пояс: UTC + 3 часа


Правила форума


ВНИМАНИЕ!

Вопросы по SAP Query и Quick View - сюда



Начать новую тему Ответить на тему  [ Сообщений: 40 ]  На страницу 1, 2, 3  След.
Автор Сообщение
 Заголовок сообщения: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 10:00 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
Ребята, может кто-нибудь знает как получить описание (компоненты) любой переменной (глобальная/локальная/структура/таблица)?

Нужно сделать что-то типа
call function 'REUSE_ALV_FIELDCATALOG_MERGE'
только с какими-то такими параметрами
i_program_name = 'ZPROGRAM'
i_internal_tabname = 'lt_bseg'
i_formname = 'my_form'
и на выходе получить компоненты таблицы lt_bseg (bukrs, belnr, gjahr, buzei).

Code:
REPORT zprogram.

TYPES:
  BEGIN OF ts_bseg,
    bukrs TYPE bseg-bukrs,
    belnr TYPE bseg-belnr,
    gjahr TYPE bseg-gjahr,
    buzei TYPE bseg-buzei,
  END OF ts_bseg.

FORM my_form.
  DATA:
    lt_bseg   TYPE STANDARD TABLE OF ts_bseg.

ENDFORM.


Я знаю, что можно использовать SCAN ABAP-SOURCE, но как-то не хочется всё это самому писать :)
Может быть, есть какие-то обёртки, чтобы это было проще сделать?


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 10:14 
Младший специалист
Младший специалист

Зарегистрирован:
Ср, авг 07 2013, 22:18
Сообщения: 61
Code:
data: lo_struct   type ref to cl_abap_structdescr,
      lt_comp     type abap_compdescr_tab,
      ls_comp     like line of lt_comp.

data: ls_header type mara.

*lo_struct ?= cl_abap_typedescr=>describe_by_name( 'MARA' ).
lo_struct ?= cl_abap_typedescr=>describe_by_data( ls_header  ).
lt_comp = lo_struct->components[].
loop at lt_comp into ls_comp.
  write: / ls_comp-name.
endloop.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 11:18 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
Programmer написал(а):
Code:
lo_struct ?= cl_abap_typedescr=>describe_by_data( ls_header  ).

Спасибо, но у меня есть доступ только к тексту исходного кода и поэтому так ls_header я не могу использовать.

Мне нужно именно извне получить описание структуры, не запуская код.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 11:39 
Специалист
Специалист

Зарегистрирован:
Ср, дек 22 2010, 19:49
Сообщения: 114
ФМ GET_GLOBAL_SYMBOLS для глобальных

_________________
Человек готов работать 24 часа в сутки, лишь бы ничего не делать.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 11:56 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
NeMurometz написал(а):
ФМ GET_GLOBAL_SYMBOLS для глобальных

Спасибо, но этот ФМ не определяет поля структуры/таблицы. Но глобальные переменные отображает, да :)

Мне нужно написать как бы статический анализатор кода.
У меня есть исходный код, который получаю при помощи READ REPORT.
Я нахожу в нём имя структуры/таблицы, у которой нужно определить структуру и поля для дальнейшего анализа.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 12:20 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, окт 06 2005, 16:44
Сообщения: 3080
Откуда: Москва
UKY написал(а):
Я нахожу в нём имя структуры/таблицы, у которой нужно определить структуру и поля для дальнейшего анализа.

Может расскажете, какая цель у этой задачи?

_________________
С уважением,
Удав.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 13:55 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
Удав написал(а):
UKY написал(а):
Я нахожу в нём имя структуры/таблицы, у которой нужно определить структуру и поля для дальнейшего анализа.

Может расскажете, какая цель у этой задачи?


Цель - проверить правильность передачи параметров в метод с TYPE ANY.

Например, есть такой код:
Code:
TYPES:
  BEGIN OF ts_bseg,
    bukrs TYPE bseg-bukrs,
    belnr TYPE bseg-belnr,
    gjahr TYPE bseg-gjahr,
    buzei TYPE bseg-buzei,
  END OF ts_bseg.

DATA:
  ls_bseg   TYPE ts_bseg.

select(
   EXPORTING   iv_table  = 'BSEG'
   IMPORTING   e_data    = ls_bseg ).


Метод объявлен примерно так:
Code:
*IV_TABLE   Importing   Type   DD03K-TABNAME   Название таблицы для выборки
*E_DATA   Exporting   Type   ANY            Выбранные данные (структура/таблица с полями из IV_TABLE)
METHOD select.
   SELECT (all_components_from( e_data ))
      INTO e_data
      FROM (iv_table).
ENDMETHOD.


Мне нужно проверить, что в ls_bseg нет никаких лишних полей, из-за которых метод SELECT может вылететь дамп.
Т.е. будет написан тестовый класс (FOR TESTING), который будет проверять правильность написанного.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 14:10 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Пн, мар 28 2005, 15:38
Сообщения: 1257
UKY: Как мне кажется, у вас неправильное понимание зачем нужны тестовые классы. Они вообще-то должны тестировать поведение софта в различных случаях... Они не должны проверять правильность написания кода.
... и это я еще не касаюсь странного метода.. если так хочется такой динамики - ну так и используйте стандартную функциональность, благо такой чуть более чем дофига теперь.
Если же хочется проверять правильность параметра - опять же, проверяйте его в самом методе с помощью rtts классов, например: получите через cl_abap_structdescr=>describe_by_data() описание переданного параметра, и сравните с ожидаемым.
А можно и вовсе выбирать по принципу: выбрать все что можно, через использование select ... into corresponding fields of...

_________________
Там, где я рос, единственным развлечением было запоминать число «π».(С) Н. Стивенсон


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 14:33 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, сен 09 2004, 07:32
Сообщения: 777
Откуда: Москва
Пол: Мужской
Я так понял, вам нужно что-то вроде этого :roll: :
Code:
  DATA: bsik_fields TYPE TABLE OF rstrucinfo-compname.
...
  DATA: icomps LIKE rstrucinfo OCCURS 0 WITH HEADER LINE.

  CALL FUNCTION 'GET_COMPONENT_LIST'
    EXPORTING
      program    = gd_repid
      fieldname  = 'WA_BSIK'
    TABLES
      components = icomps.

  REFRESH bsik_fields.
  LOOP AT icomps.
    APPEND icomps-compname TO bsik_fields.
  ENDLOOP.
...
  SELECT  (bsik_fields)                " открытые позиции
...

_________________
"Прежде чем сделать что-то, подумай, к чему это может привести..."


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 15:49 
Старший специалист
Старший специалист

Зарегистрирован:
Чт, май 12 2011, 16:06
Сообщения: 351
UKY написал(а):
Мне нужно проверить, что в ls_bseg нет никаких лишних полей, из-за которых метод SELECT может вылететь дамп.
Тогда, по идее, нужно получить список полей таблицы iv_table (таблица DD08L или ФМ VIEW_GET_FIELDTAB или DP_GET_FIELDS_FROM_TABLE), после чего проверить, что все поля, возвращаемые all_components_from(), содержаться в iv_table. Правда, в таком случае не проверяется, что поле принадлежит типу ts_bseg, но, исходя из проблемы, это и не нужно.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Вт, июн 10 2014, 15:58 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, окт 06 2005, 16:44
Сообщения: 3080
Откуда: Москва
Кодер написал(а):
А можно и вовсе выбирать по принципу: выбрать все что можно, через использование select ... into corresponding fields of...

+1
Code:
METHOD select.
  DATA: lv_typ type c.

  DESCRIBE FIELD e_data TYPE lv_typ.

  CASE lv_typ.
    WHEN 'u'. "Структура
      SELECT *     
      INTO CORRESPONDING FIELDS OF e_data
      FROM (iv_table)
      WHERE (iv_where).
    WHEN 'v'. "Внутренняя таблица
      SELECT *     
      INTO CORRESPONDING FIELDS OF TABLE e_data
      FROM (iv_table)
      WHERE (iv_where).
    WHEN OTHERS.   
  ENDCASE.

ENDMETHOD.

_________________
С уважением,
Удав.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Ср, июн 11 2014, 04:07 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
**Был дабл-пост

Всем спасибо за ответы!


Последний раз редактировалось UKY Ср, июн 11 2014, 04:19, всего редактировалось 1 раз.

Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Ср, июн 11 2014, 04:18 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
Кодер написал(а):
UKY: Как мне кажется, у вас неправильное понимание зачем нужны тестовые классы. Они вообще-то должны тестировать поведение софта в различных случаях... Они не должны проверять правильность написания кода.

Это я понимаю, но мне же ничего не мешать тестировать не только логику приложения, но и производить статический анализ кода?
Я хотел все эти проверки внедрить в "анализатор кода" (тр. SCID), но, увы, не смог этого сделать. Поэтому и решил все эти проверки делать в тестовых классах.

Кодер написал(а):

... и это я еще не касаюсь странного метода.. если так хочется такой динамики - ну так и используйте стандартную функциональность, благо такой чуть более чем дофига теперь.

Я намеренно упростил код, чтобы было понятнее, что мне нужно.
На самом деле метод гораздо сложнее: формирует WHERE, убирает дублирующиеся ключи для FOR ALL ENTRIES, при использовании буферных внутренних таблиц не делает повторные выборки по одним и тем же ключам и по ключам, которых нет в БД, расширяет возможности стандарта по выборке данных и т.д. и т.п...
Т.е. метод убирает всю рутинную работу, которую приходится делать программисту вручную, до минимума снижает нагрузку на БД.

Кодер написал(а):

Если же хочется проверять правильность параметра - опять же, проверяйте его в самом методе с помощью rtts классов, например: получите через cl_abap_structdescr=>describe_by_data() описание переданного параметра, и сравните с ожидаемым.

Правильность параметра я и так проверяю в самом методе через RTTS классы. Но мне нужно знать о неправильности переданных данных до того, как код будет запущен.

Кодер написал(а):

А можно и вовсе выбирать по принципу: выбрать все что можно, через использование select ... into corresponding fields of...

CORRESPONDING FIELDS OF не подходит ввиду его эффективности. Например, мне из BSEG нужно всего 4 ключевых поля (BUKRS, BELNR, GJAHR, BUZEI, которые можно вытянуть даже через index only scan), а если писать SELECT * INTO CORRESPONDING FIELDS СУБД придётся вытаскивать из таблицы и передавать по сети порядка 400 полей, которые мне совсем не нужны...

nicky555 написал:
Я так понял, вам нужно что-то вроде этого :roll: :
Code:
CALL FUNCTION 'GET_COMPONENT_LIST'

Спасибо! Этот ФМ возвращает компоненты, но, к сожалению, не для всех структур (например, локальные вообще не видит).

LAT написал(а):
Тогда, по идее, нужно получить список полей таблицы iv_table (таблица DD08L или ФМ VIEW_GET_FIELDTAB или DP_GET_FIELDS_FROM_TABLE), после чего проверить, что все поля, возвращаемые all_components_from(), содержаться в iv_table. Правда, в таком случае не проверяется, что поле принадлежит типу ts_bseg, но, исходя из проблемы, это и не нужно.

Да, именно это мне и надо сделать :) Только мне хотелось бы всё это проверить ДО ЗАПУСКА кода. А то, например, в IV_TABLE подсунут несуществующую таблицу и опа - дампик готов...



Чтобы было понятнее, почему я это всё задумал, вот более полный вызов метода:
Code:
  DATA:
    BEGIN OF lt_mkpf OCCURS 0,
      mblnr      TYPE mkpf-mblnr,
      mjahr      TYPE mkpf-mjahr,
      bukrs      TYPE mkpf-bukrs,
      zzbelnr   TYPE mkpf-zzbelnr,
      zzgjahr   TYPE mkpf-zzgjahr,
      zzmat      TYPE mkpf-zzmat,
    END OF lt_mkpf,
    BEGIN OF lt_bseg OCCURS 0,
      bukrs      TYPE bseg-bukrs,
      belnr      TYPE bseg-belnr,
      gjahr      TYPE bseg-gjahr,
      buzei      TYPE bseg-buzei,
    END OF lt_bseg,
    gst_bseg LIKE SORTED TABLE OF lt_bseg WITH UNIQUE DEFAULT KEY.

* Вызов метода
   select(
      EXPORTING
         i_key      = lt_mkpf[] " Ключи для выборки (таблица)
         iv_comp   = `BUKRS BELNR=ZZBELNR GJAHR=ZZGJAHR MATNR='00000000'ZZMAT AUGDT=&SY-DATUM& DMBTR>'0' WRBTR=&I_VAR1& KOART=&I_VAR2& SHKZG=&I_VAR3&`   " Условия выборки: через пробел несколько компонентов (компонент таблицы)[знак[(компонент ключа)]]|('константа')|(&переменная&)]
         i_var1   = '100'   " Значение 1-ой переменной в фильтре (WRBTR=&I_VAR1&)
         i_var2   = ls_bseg-koart   " Значение 2-ой переменной в фильтре (KOART=&I_VAR2&)
         i_var3   = lr_shkzg   " RANGE
         iv_table   = 'BSEG'   " Таблица, из которой производить выборку
      IMPORTING
         e_data   = lt_bseg   " Выбранные данные
         ev_subrc   = lv_subrc   " Флаг наличия выбранных данных
      CHANGING
         ct_buf   = gst_bseg ).   " Все когда-либо выбираемые данные из БД по этой таблице дублировать в буферную переменную gst_bseg

* Делает практически тоже самое, что и
        SORT lt_mkpf BY bukrs zzbelnr zzgjahr zzmat.
        DELETE ADJASENT DUPLICATES FROM lt_mkpf COMPARING bukrs zzbelnr zzgjahr zzmat.
        DELETE lt_mkpf WHERE bukrs IS INITIAL AND zzbelnr IS INITIAL AND zzgjahr IS INITIAL AND zzmat IS INITIAL.

        IF NOT lt_mkpf[] IS INITIAL.
          " Если есть все данные или часть выборки есть в gst_bseg (и по заданным ключам они были в БД), то данные берутся из gst_bseg и кладутся в lt_bseg.
          " Если каких-то данных в gst_bseg нет, то делает такую выборку:
          SELECT bukrs belnr gjahr buzei
          INTO TABLE lt_bseg
          FROM bseg
          FOR ALL ENTRIES IN lt_mseg
          WHERE bukrs = lt_mseg-bukrs
            AND belnr = lt_mseg-zzbelnr
            AND gjahr = lt_mseg-zzgjahr
            AND matnr = |00000000{ lt_mseg-zzmat }| " Стандартный SELECT не может так делать
            AND augdt = sy-datum
            AND dmbtr > '0'
            AND wrbtr = '100'
            AND shkzg IN lr_shkzg.

          " Если каких-либо данных не было в gst_bseg, то они добавляются туда из lt_bseg
        ENDIF.

В этом коде мне хотелось бы проверить (не запуская его, т.е. как бы при компиляции), что поля из IV_COMP (BUKRS, BELNR, GJAHR, AUGDT, DMBTR, WRBTR, KOART, SHKZG) есть в IV_TABLE (BSEG) и что поля из IV_COMP (BUKRS, ZZBELNR, ZZGJAHR, ZZMAT) имеются в lt_mkpf.
Для этого я пишу тестовый класс, который запускается при нажатии CTRL+SHIFT+F10, читает код, заменяет вызов метода на стандартный SELECT, делает проверку синтаксиса. Если имеются какие-либо ошибки, то указывается строка кода, в которой есть ошибка и текст ошибки.
Другого выхода я не придумал. Ну, разве что писать код сразу без ошибок :)


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Ср, июн 11 2014, 09:02 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Пн, мар 28 2005, 15:38
Сообщения: 1257
Цитата:
Это я понимаю, но мне же ничего не мешать тестировать не только логику приложения, но и производить статический анализ кода?

Можно забивать гвозди микроскопом, но эффективнее - молотком. Статический анализ кода для динамики - это уже атас. Опять же, а что за проблема была со SCID?
Цитата:
Я намеренно упростил код, чтобы было понятнее, что мне нужно.
На самом деле метод гораздо сложнее: формирует WHERE, убирает дублирующиеся ключи для FOR ALL ENTRIES, при использовании буферных внутренних таблиц не делает повторные выборки по одним и тем же ключам и по ключам, которых нет в БД, расширяет возможности стандарта по выборке данных и т.д. и т.п...
Т.е. метод убирает всю рутинную работу, которую приходится делать программисту вручную, до минимума снижает нагрузку на БД.

У меня сильное подозрение, что Вы изобретаете велосипед. Причем с квадратными колесами. Различные динамические ухищрения чаще всего работают медленнее чем статически описанные конструкции. Динамика нужна в строго определенных дозах
Цитата:
Правильность параметра я и так проверяю в самом методе через RTTS классы. Но мне нужно знать о неправильности переданных данных до того, как код будет запущен.

Зачем? Ну зачем все это?
Цитата:
CORRESPONDING FIELDS OF не подходит ввиду его эффективности. Например, мне из BSEG нужно всего 4 ключевых поля (BUKRS, BELNR, GJAHR, BUZEI, которые можно вытянуть даже через index only scan), а если писать SELECT * INTO CORRESPONDING FIELDS СУБД придётся вытаскивать из таблицы и передавать по сети порядка 400 полей, которые мне совсем не нужны...

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

Инструмент, который Вы изобретаете уже есть в системе.

_________________
Там, где я рос, единственным развлечением было запоминать число «π».(С) Н. Стивенсон


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Получить описание переменной
СообщениеДобавлено: Ср, июн 11 2014, 09:36 
Специалист
Специалист

Зарегистрирован:
Вт, июн 10 2014, 09:41
Сообщения: 180
Кодер написал(а):
Опять же, а что за проблема была со SCID?

Просто не нашёл как внедрить туда свою логику обработки кода программы.

Кодер написал(а):
У меня сильное подозрение, что Вы изобретаете велосипед. Причем с квадратными колесами. Различные динамические ухищрения чаще всего работают медленнее чем статически описанные конструкции. Динамика нужна в строго определенных дозах

Да, это велосипед, но он чертовски удобен.
Да, работает медленнее, чем нормально написанный код. Но работает медленнее только на сервере приложений, на уровне СУБД только необходимые выборки, причём с использованием SAP BUFFERING.
Весь смысл этого велосипеда - снизить до минимума обращение к БД, сделать код лаконичнее и понятнее, без всяких промежуточных структур/таблиц и т.п...

Кодер написал(а):
Цитата:
Правильность параметра я и так проверяю в самом методе через RTTS классы. Но мне нужно знать о неправильности переданных данных до того, как код будет запущен.

Зачем? Ну зачем все это?

Для уменьшения количества ошибок и дампов, если вдруг программист очепятался, например, или передал неправильные данные в метод и эта ветка кода не была протестирована (читай - выполнена в реалтайме).
Вам было бы удобно использовать SELECT, если бы он не говорил, что нет каких-нибудь полей в таблице, недавал подставлять названия таблиц, полей и т.п.? Мне вот сейчас со своим веросипедом в каком-то виде стало не удобно :)

Кодер написал(а):
Это вообще - в мемориз. Крайне рекомендую ознакомится с тем, как хранятся данные BSEG. Это кластерная табла. В результате - при вытаскивании даже одного поля, запрос будет тащить всю строку и парсить ее на аппликейшене.

BSEG я привёл для примера. Можно вставить любое название таблицы :)
И аппликэйшену не обязательно тащить всю строку из кластерной таблицы и парсить её. Например, из кластера таблиц RFBLG можно безболезненно взять поля BUKRS, BELNR, GJAHR ;) Но другие поля да, придётся парсить :)

Кодер написал(а):
Инструмент, который Вы изобретаете уже есть в системе.

Спасибо за ссылку! Про такую штуку я только слышал, но ни разу не использовал.
Это не совсем то, что я изобретаю.
Там используется NATIVE SQL: т.е. нет поддержки SAP BUFFERING, приходится вручную вводить MANDT, нет FOR ALL ENTRIES, нет кроссплатформенности СУБД (хотя я не верю в переход с одной СУБД на другую :) ).
Да и судя по примеру использовать её не так уж и просто и ошибок можно наделать ещё больше, чем в моём велосипеде (:
result = sql->execute_query(
`SELECT carrid, connid, fldate ` &&
`FROM sflight ` &&
`WHERE mandt = ` && `'` && sy-mandt && `' AND` &&
` carrid = ` && `'` && p_carrid && `'` ).
result->set_param_table( itab_ref = dref
corresponding_fields = cols ).

Вся задумка в анализе кода в том, чтобы дополнительно обезопасить программиста от ошибок ДО запуска кода.
Можете переубеждать меня сколько угодно, что мой велосипед не нужен, но я сделал свой выбор и вполне им доволен :)
Не доволен только повышением вероятности наделать ошибок просто очепятовшись или что-то не дописать в структурах.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 40 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB