Какво е LBG[]
LBG е свободната(GPL) версия на уеб приложението което движи сайта Linux-BG . Посетете страницата за да видите кои сайтове използват също LBG системата.
Какво ново[]
- Добавена е страница с информация за последните документи и новини (index.pl?page=recent)
- Съдържанието на последните документ може да бъде получено и като RSS или JSON документ като например - http://labs.linux-bg.org/cgi-bin/code/index.pl?act=ws
Ако искате да видите съдържанието като JSON - http://labs.linux-bg.org/cgi-bin/code/index.pl?act=ws&format=json
- Добавена е възможност за показване на случаен документ
Като например - http://labs.linux-bg.org/cgi-bin/code/index.pl?page=docs&cmd=random
- Клониране на документ - освен обичайното добавяне, редактиране и изтриване е добавено и клониране на документ. Клонирането помага за създаването на нов документ на базата на съществуващ. Особено полезно за MadeInBG секцията
- Заключване/Октлючване на документ за редакции
- Разрешаване/Забравянване за добавяне на коментари към документ
- CustomTag::Geo
Използването на този таг в съдържанието на документ ще покаже карта (от google map) с положението на обекта. Допълнително може да търсите за обекти в радиуйс от X километра до този. Пример: Linux-BG Conference Съдържанието: И тази година ... [geo coord="23.454545;48.2313123" zoom="12"]Конферентна зала "При орлите"[/geo]
- CustomTag::Event Използвано на този таг в съдържанието добавя календар на който са отбелязани посочените от вас дати. Информацията за събитието се записва в база и в последтвие може да се търсят събития от дата до дата
Пример: Linux-BG Conference Съдържанието: И тази година ..... [event start="2007-07-21 13:00" end="2007-07-21 16:00"]Linux-BG Conference for July[/event]
- Възможност за различна форма за добавяне/редактиране на даден тип документ (Полезно за MadeInBG, Галерия, Дистрибуции...)
- Възможност за различен шаблон при показване на даден тип документ (Полезно за MadeInBG, Галерия, Дистрибуции...)
+ Микроформати за Geo и Event етикетите
Инсталиране[]
Инсталиране[]
За да инсталирате приложението трябва да следвате следните стъпки:
- Разархивираните и копитайте файлове в cgi-bin директорията на вашия уеб сървър.
- Влезте в директорията "cd lbg/"
- От вашият уеб браузър извикайте програмата http://localhost/cgi-bin/lbg/install/setup.pl
- След успешно инсталиране на приложението забранете стартирането на setup.pl скрипта.
- chmod a-x install/setup.pl - Изпълнете командата в главната директорията където е приложението.
- Разгледайте генерирания config.pm файл в главната директория на приложението и променете нещо по него ако се налага.
SVN Инсталиране[]
За да инсталирате приложението трябва да следвате следните стъпки:
- Създайте поддиректория code във cgi-bin директорията на вашия уеб сървър.
- Влезте в тази директория "cd code"
- Свалете приложението от Internet посредством Subversion
svn checkout https://svn.openfmi.net/linux-bg/trunk/
- От вашият уеб браузър извикайте програмата http://localhost/cgi-bin/code/install/setup.pl
- След успешно инсталиране на приложението забранете стартирането на setup.pl скрипта.
- chmod a-x install/setup.pl - Изпълнете командата в главната директорията където е приложението.
- Разгледайте генерирания config.pm файл в главната директория на приложението и променете нещо по него ако се налага.
Структурата на директориите и за какво те се използват[]
+- -- Главната директория за системата index.pl -- Основният пърл скрипт който определя какво да се прави config.pm -- Основният конфигурационен файл. В него се описва и къде се намира директориите по-долу sql/ -- Директория с файловете необходими за създаването на таблиците в базата които се използват от системата src/ -- Директорията в която стоят пърл скриптовете. packages/ -- Директорията с класовете(пакетите) които използва системата test/ -- Директорията в която стоят скриптовете тестващи дали даден клас работи правилно и достатъчно бързо page/ -- Директорията в която стоят файлове който се зареждат пред визуализирането на дадена страница. act/ -- Директорията в която стоят файловете отговарящи за определени действия. Като промяна данните на потребител например. За пример може да разгледате файла user_profile.pl намиращ се в src/act/ директорията inc/ -- Директорията с помощните пърл файлове. lang/ -- Тук се намират файловете описващи съобщенията които използваме на различните езици. bg/ themes/ -- Темите в сайта. common-config.pm base/ system/ cache/ bluj2/ ... htdocs/ -- директория в която се намират нещата които са видими през браузъра themes/ -- Файловете за дадена тема. base/ blju2/ ... js/ default_images/ data/ -- Данни необходими на системата за да работи. Тази директория не трябва да се вижда през браузър. logs/ pages/ -- Описание на страниците в сайта.
Как работят шаблоните[]
За повече информация как работят шаблоните които използваме, влезте в директорията src/tests/ и от там изпълнете следната команда:
perl template_demo.pl
Може да видите как изглежда един шаблон като разгледате файла main.tmpl в същата директория.
За да видите как да използвате този шаблон във вашата Пърл програма разгледайте файла template_demo.pl .
Как се структурират и използват темите и шаблоните[]
Този документ описва как се структурират и използват темите и шаблоните от системата.
Дефиниции[]
- Шаблон: текстов файл в който се пази информация която се визуализира от системата.
- Тема: съвкупност от шаблони, групирани по външен вид.
Използвани директории[]
Двете основни директории където се пази информацията за темите които използваме в системата са (в конкретния случай): - themes/ -- в тази директория се пазят различните теми. За тази директория е за предпочитане да не се вижда от браузъра.
- htdocs/themes/ -- в тази директория се пази информация свързана с темите, която трябва да се вижда и зарежда от браузъра. За пример тук се пазят картинките, CSS, JavaScript файловете и д.р. Получер текст
Конфигуриране[]
В системата има възможност да сложите themes/ и htdocs/themes/ директориите на съвсем различни места. За целта трябва да промените настройките записани в config.pm файла намиращ се в главната директория. Променливите които отговарят за тези настройки са $CONFIG{THEME_DIRECTORY} и $CONFIG{THEME_DATA_DIRECTORY} съответно. =
Организация в themes/ директорията[]
В тази директория всяка различна тема, която използваме в сайта, стои в собствена поддиректория. Ще забележите следните директории:
base/ system/ cache/ blju2/ system/ cache/
Ако добавяме нова тема, то тя отново трябва да има същата структура.
В основната директория с шаблоните за различните теми се намира файла common-config.pm в който стоят общите настройки за всички теми. Допълнително в директорията на всяка тема, като base/ например, има файл config.pm с настройките само за конкретната тема. Т.е структурата става така:
themes/ common-config.pm base/ config.pm system/ cache/ _ime_na_temaN/ config.pm system/ cache/
В главната директория на всяка тема се пазят основните шаблони отговарящи за структурата на отделните страници. В под-директорията system/ се пазят шаблоните за отделни често повтарящи се елементи в една страница. Като менюто например.
Ако зареждаме страницата help то шаблона трябва да се казва help.tmpl.
Ако една страница използва шаблона help.tmpl то този файл трябва да се казва така във всички теми.
Възможности при дефинирането на тема[]
- Задава се една основна тема в която трябва да присъстват всички необходими от нас шаблони. Това се задава с променливата $CONFIG{BASE_THEME_NAME} в конфигурационния файл config.pm nамиращ се в главната директория(там където е и index.pl файла).
- За всяка тема допълнително може да се зададе дали да използва(наследява) елементи от друга тема. Така например темата blju2 използва шаблони от темата blju. Програмистите използващи обектно ориентирани езици могат да мислят за това като за един вид наследяване.
Стъпки при зареждане на шаблон за страница[]
Когато се определя кой шаблон да се зареди за дадена страница се преминава през следните стъпки.
- Вижда се коя е текущата тема.
- Гледа се дали в директорията на тази тема присъства шаблон отговарящ на името на страницата.
- Ако има такъв шаблон - той се използва.
- Ако няма такъв - се проверява дали в конфигурацията на темата не е зададено, че *Ако наследява друга тема и там има шаблона който търсим - използваме него.
- Ако няма такъв шаблон в директорията на темата която наследяваме, тогава търсим този шаблон в основната тема.
Нещата са организирани така не (само) за да ви затрудняваме да разберете как функционира всичко, а за да избегнем появата тук и там на множество повтарящи се шаблони.
Пример 1: Ако темата blju2 променя само някои шаблони в темата blju, то не е нужно да копираме всички шаблони от blju в blju2, а само да окажем в конфигурацията на темата blju2, че наследява blju INHERIT_THEME_NAME и в директорията на темата blju2 да сложим само шаблоните които се различават.
Пример 2: Различните теми може да използват шаблон който визуално изглежда по един и същ начин. За тази цел не е нужно този шаблон да присъства във всички теми, и ако решите да променяте нещо по него да повторите тази промяна във всички шаблони. Такъв шаблон трябва да присъства САМО в основната тема.
С тази организация избягваме повтаряща се, излишна, информация и улесняваме редактирането. Ако разберете логиката по-горе значи сте готов да създадете нова тема за сайта.
Организация в htdocs/themes/ директорията[]
Както в themes/ директорията и тук имаме отделни поддиректории за всяка тема. Имената на тези директории трябва да са същите като имената на темите. Във всяка директория на тема се слагат отделните файлове с картинки, CSS, JavaScript код и т.н, ако дадената тема се нуждае от картинки.
Основните неща за създаване на нова тема[]
Това е кратко ръководство което ще ви запознае с основните неща за създаване на нова тема. Информацията в отделните части и придружена с примери.
Основните понятия[]
Тема: Съвкупност от шаблони, която определя как визуално ще изглежда приложението. За подробности прочетете документа озаглавен Themes.txt, който се намира в тази директория. Шаблон: Нещо като HTML файл. За това какво е шаблон погледнете документа Templates.txt отново в тази директория.
Избиране на име[]
Ако сте готов с инсталирането е време да изберете име на вашата тема. За предпочитане е името да съдържа само латински букви, цифри и "_". Изберете нещо кратко за име.
Например "mytheme".
Създаване на нужните директории[]
След кaто изберете името трябва да създадете директориите където ще стоят:
1. Шаблоните на вашата тема в директорията themes/, създайте поддиректория с името на вашата тема. За нашия пример използваме името mytheme. Директорията с шаблоните трябва да изглежда горе долу така:
themes/ README common-config.pm base/ blju2/ mirco/ mytheme/ <--- Създадената от вас директория text/
1.1. Създаване на важните поддиректории в директорията themes/mytheme/ създайте две поддиректории - cache и system. Т.е структурата става нещо такова:
themes/ mytheme/ system/ cache/
2. Картинките, CSS файловете и т.н свързани с темата в директорията htdocs/themes/ създайте нова директория mytheme. Това е директорията където ще слагате картинките и т.н неща свързани с вашата бъдеща тема.
Създаване на конфигурационния файл[]
За да използвате пълните възможности на конфигурационния файл ще се нуждаете от начални познания по Perl. Ако нямате такива - няма проблем.
Създайте файл с име config.pm в директорията themes/mytheme/. Файлът трябва да съдържа следните редове:
#========== копирай от следващия ред ==== # [ Theme config file] # %hThemeSetting = ( VARS => { 'author_name' => '__ВАШЕТО_ИМЕ__', 'author_email'=> '__ВАШИЯТ_EMAIL__', 'image_url' => $main::CONFIG{'WEB_DIRECTORY'}.'/theme/mytheme', }, # config options taken into account # CONFIG => { # 'INHERIT_THEME_NAME' => '...', # }, ); 1; #========= край на текста за копиране ====
Създаване на основните шаблони в темата[]
В това ръководство сме се ограничили до създаване на най-важните шаблони за една тема. Шаблоните отговарящи за цяла страница ще записваме в директорията themes/mytheme/, а шаблоните отговарящи за отделни, повтарящи се елементи в страницата, като шаблона за менюто например, ще записваме в директорията themes/mytheme/system/
bare.tmpl[]
Създайте шаблон bare.tmpl в themes/mytheme/ директорията. bare.tmpl е шаблона отговарящ за разположението на съдържанието, менютата, и т.н. Като за начало може да разгледате шаблона bare.tmpl в директорията themes/text/.
За да не започвате от нулата може да копирате този шаблон(themes/text/bare.tmpl) във вашата директория (/themes/mytheme/). Забележете следните важни променливи в него/ $CONTENT_DATA - това се заменя със съдържанието на конкретната страница. $FULL_NAVIGATION_MENU - това се заменя с менютата $ACTION_RESULTS - това се заменя с кратката информация, която се появява при вход в системата, например.
Всички променливи които са записани в конфигурационния файл също се заменят с дадената от вас стойност. Например ако сложите във шаблона $author_name ще видите, че тя се заменя с посоченото от вас име.
system/box.tmpl[]
Това е шаблона отговарящ за декорацията, която се появява около някои страници. Или "кутията" около тях.
Важни променливи тук са:
$boxTitle - заглавието $boxContent - съдържанието
За пример разгледайте themes/text/system/box.tmpl
[]
Това е шаблона отговарящ за менютата,
Важни променливи тук са:
$title - заглавието на менюто. $menu_items - съдържанието на отделните редове в менюто
За пример разгледайте themes/text/system/menu.tmpl
Използване на картинки във шаблоните[]
Ако използвате картинки за дизайна на вашите шаблони е добре всички картинки да бъдат записани в директорията: htdocs/themes/mytheme
След което във вашите шаблони за зареждането на картинка, примерно x.png, използвайте следното: <img src="$image_url/x.png">
Това е. По време на обработката на шаблона $image_url ще се замени с директорията в която са картинките и всички би трябвало да си дойде на мястото.
Разрешаване на темата[]
За да използвате новосъздадената тема трябва да я разрешите в главния конфигурационнен файл. Той се казва config.pm и се намира в главната директория на приложението, там където е и index.pl. Намерете следните редове:
$CONFIG{AVAILABLE_THEMES} = ({ 'base' => 1, 'blju2' => 1, 'text' => 1, 'mirco' => 1, });
и ги промете да изглеждат така:
$CONFIG{AVAILABLE_THEMES} = ({ 'base' => 1, 'blju2' => 1, 'text' => 1, 'mirco' => 1, 'mytheme' => 1, });
След което запишете файла.
Тестване на новата тема[]
Готови ли сте. Време е да тествате новата тема. За целта въведете следния адрес във вашия браузър:
http://localhost/index.pl?page=themes&act=look&cmd=change&look=mytheme
Информация за напреднали[]
Специални шаблони за вашата тема[]
Ако не искате да използвате стандартните шаблони, примерно за страницата "Профил", може да копирате във вашата директория themes/mytheme/ файла от /themes/base/profile.tmpl и да го редактирате, така че да напасне на вашата тема.
Наследяване на тема[]
Това ще рече че може да използвате шаблоните на съществуваща тема и само да промените някои страници или елементи по тях за да създадете новата тема. За целта трябва да редактирате конфигурационния файл на вашата тема:
themes/mytheme/config.pm
Махнете символа # от следните редове:
- CONFIG => {
- 'INHERIT_THEME_NAME' => '...',
- },
И заменете '...' с името на темата която ще надграждате. След редакция тези редове може да изглеждат така:
CONFIG => { 'INHERIT_THEME_NAME' => 'text', # Използвате темата text и надграждаме },
Добавяне на нова страница в системата[]
Този документ описва какво е нужно да направите за да добавите нова страница в системата. Това е начина по който работят страниците в сайта, в момента, но той може да се промени в бъдеще.
Описание на една страница[]
Описанието на една страница се задава във файла data/pages/pages.dat
Всеки ред отговаря за описанието на отделна страница.
За да опишете една страница трябва да зададете няколко неща.
- Име на страницата(за предпочитане латински букви). Пример: profile
- Заглавие на страницата. Пример: Вашият профил
- Дали около страницата се слага "рамка". Стойностите които може да използвате тук са 0 или 1
- Дали тази страница използва помощен Пърл файл преди да се визуализира.
Пример: profile.
Ако не използвате помощен файл, то оставяте празно. Това описание изглежда така във файла:
profile#^#Вашият профил#^#1#^#profile
Къде се слагат различните компоненти[]
Името на страницата, в нашия случай profile, всъщност е името на шаблона който използва тази страница. За да разберете какво е шаблон, прочетете Templates.txt документа. Шаблонът за една страница може да е различен за различните теми [виж: Themes.txt]. За да видите как изглежа шаблона който използваме за конкретния пример може да разгледате файла themes/base/profile.tmpl
Пърл файлът който използваме преди визуализирането на страницата трябва да се намира в директорията pages/. Името му се образува от точка 4 по-горе и .pl накрая. В нашият конкретен случай то е profile.pl. Може да го разгледате от: pages/profile.pl
За какво служи файлът data/pages/page.pm[]
Този файл преобразува информацията от описателния файл data/pages/pages.dat в Пърл файл. Това се прави за ускоряване зареждането на този спиъск със страници.
Когато променяте нещо по описателния файл е добре след това да изтриете data/pages/page.pm файла. Той ще бъде генериран автоматично от системата.
Забележка: НЕ трийте файла: data/pages/pages.dat !
Добавяне или подобряване на програмен текст[]
Ако желаете да добавите или подобрявате програмен текст, моля използвайте следните правила за форматиране:
Правило 1: Подравняване
Използвайте табулации от 8 символа. Съдържанието на всеки нов блок го подравнявайте с една табулация. Това прави нещата лесни за четене и помага при разчитането на програмния текст, дори и ако той е написан на език като Пърл, славещ с това че е лесен за писане, но труден за четене.
Правило 2: Поставяне на къдравите скоби
Използвайте стила зададен от Кърнигам и Ричи. И той е - отварящата скоба се поставя след последна команда на реда, а затварящата се слага първа на нов ред. Т.е:
if ($x==1) { print "Hello\n"; } elsif($x==2) { print "Hi again\n"; } else { print "By\n"; }
За функциите използвайте същото правило
sub functionX { my ($x) = @_; # .... }
Както може да се досетите това важи за while
while(condition) { body of do-loop }
и do ... while конструкциите
do { body of do-loop } while (condition);
Има много дискусии кой стил за поставяне на скоби е по-добър. Ние използваме този, без да твърдим, че е най-добрия и ви молим да използвате него.
Правило 3: Именоване
Използвайте кратки и ясни имена за променливи и функции.
1. На променливи Променливите започват с малка буква и ако са съставени от няколко думи всяка дума, освен първата, започва с главна буква. Старайте се да използвате само латински букви и евентуално числа, като избягвате други символи, като "_" например. Пример:$file
1.2. Скаларни променливи 1.2.1. Ако стойността която ще се съхранява е стринг Използвайте представката "s", т.е променливата трябва да се именова: $sFileName 1.2.2. Ако стойността която ще се съхранява е число, без значение какво. Използвайте представката "n". Няма значение дали очаквате цели числа, числа с плаваща запетая и т.н Т.е променливата трябва да се именова: $nFileSize 1.2. Масиви - За масивите използвайте представка "a". Пример: @aFileSizes 1.3. Хешове - За име на хеш използвайте представката "h". Пример: %hFileInfo 1.4. Обекти За име на обект използвайте представката "o". Пример: $oUser = User->new(); 1.5. Референции - Ако променлива съдържа указател/референция към друга променлива, то тя се именова с представката "ref". Пример: $refName = $sName; 2. На функции - Правилата са като при именоване на променливи, без да се използват представки. Пример:
sub getName { # ... }
3. На пакети - Името на пакет започва с главна буква и ако е съставено от няколко думи, то всяка следваща дума започва отново с главна буква. Старайте се да използвате само латински букви и евентуално числа, като избягвате други символи, като "_" например. Пример: package UserManager;
Правило 4: Описване на функция
Именоването на функциите е описано в по-горната глава. Използвайте кратки и смислени имена. При задаването на входните параметри на дадена функция ги записвайте по следния начин:
sub function {
my ( $sName, $nSize, ) = @_; }
За предпочитане е една функция да изпълнява само едно нещо и да го изпълнява добре. Дължината на една функция е обратно пропорционална на нейната сложност. Това ще рече, че ако една функция е сложна, то тя трябва да е кратка или да се раздели на няколко функции, които са сравнително кратки. От друга страна ако една функция е сравнително проста, то е позволено тя да бъде и малко по-дълга.
Друго което е добре да се съобрази в една функция е броя на локалните променливи. Те не трябва да надвишават 5-10. Ако вашата функция има повече локални променливи това може да означава, че е време да преосмислите вашата функция. Човешкият мозък може да се справи с проследяването на 7 различни неща, но след това той се обърква.
Друго ценно правило при писането на функции е, когато погледнете текста на функцията след две седмици да сте напълно наясно какво прави тя. В противен случай е добре да преосмислите вашия програмен текст.
Правило 5: Коментиране За коментар използвайте стандартния знак за Пърл - символa диез "#".
Правило 6: Инициализиране на променливи. Инициализирайте вашите променливи в началото, където това е възможно.
Правило 7: Задължителни директиви За по-лесно откриване на потенциални грешки използвайте директивата use strict;
Управление на потребителите, правата и сесиите[]
Следните класове, намиращи се в директорията src/packages/ отговарят за потребителите, правата им и техните сесии:
UserManager.pm SessionUser.pm Session.pm
както и следните sql файлове, намиращи се в директорията sql/
users.sql user_permissions.sql user_roles.sql sessions.sql
Права и роли[]
Какво може да прави даден потребител в сайта се определя от неговите права или роли. Ролята е съвкупност от права. Всяко права и всяка роля могат да имат срок до който са валидни.
Т.е може да създадем роля - редактор на новини(включваща правата за активиране на новина, която не е публикувана все още, редактиране на новина, активиране на редакция на новина) и да я закачим за някой потребител в сайта. Допълнително може да кажем че тези права са валидни в рамките на два дни. По този начин може да проверим някой желаещ от сайта дали става за редактор на новините.
Това ни помага да направим следните неща:
- Да дадем право на потребител в сайта да редактира новини
- ... или да редактира конкретна новина
- Да дефинираме роля - временен модератор, който в период от 24 часа да има право да редактира новините, статиите или да активира коментари
- Да имаме потребител който може само да активира коментари, без да ги редактира
- и д.р.
Session.pm =[]
Класът Session е класът който се грижи за отделните сесии в системата и манипулациите с тях и тяхната валидност.
$oSession = Session->new(...);
По важни неща които са реализирани в този клас:
- Проверка дали дадена сесия е валидна $oSession->isValid();
- Добавяне на нова сесия $oSession->add()
- Обновяване на съществуваща сесия $oSession->update()
- Изтриване на сесия $oSession->delete();
- Вземане на "уникалния" идентификатор на сесията $oSession->getID();
- Вземане на цялата информация за текущата сесия $oSession->getContent();
SessionUser.pm[]
Класът SessionUser отговаря за правата, настройките и данните който има даден логнат в системата потребител.
$oUser = SessionUser->new( ... );
С него могат да се реализират следните неща:
- Да се зададе, че текущия потребител е този, който има ID 333 в базата $oUser->setUser(333);
- Да се вземе информация за текущия потребител - примерно неговото име $oUser->getData('name');
- Да се вземе конкретна настройка за текущия потребител - примерно от коя страна се намират неговите менюта $oUser->getSetting('menu_pos');
- Да се провери дали текущия потребител има право да редактира новини
$oUser->hasPermission('EDIT_NEWS');
- Дали потребителя има право да редактира конкретна новина ( конкретно в сайта използваме тази функционалност за определяне дали потребителят може да редактира дадена категория във "Връзки" ) $oUser->hasPermission('EDIT_NEWS',3455121);
UserManager.pm[]
Това е класът отговарящ за манипулациите с потребители.
$oUserManager = UserManager->new (...);
Това включва:
- Добавяне/редактиране на потребител
$oUserManager->addUser(...); $oUserManager->setUser(...); $oUserManager->getUserField(...); $oUserManager->setUserField(...);
- Добавяне/редактиране на настройките на потребител
$oUserManager->setUserSettings(); $oUserManager->getUserSettings();
- Определяне дали даден потребител има дадено право $oUserManager->hasPermission(...);
- Добавяне/редактиране/изтриване на права на потребител // ToDo:...
- Добавяне/изтриване/редактиране на ролите на потребител // ToDo:...
Ръководствата за програмиста[]
Ръководствата за програмиста може да намерите в поддиректорията docs/ Или от интернет на адрес: http://openfmi.net/plugins/scmsvn/cgi-bin/viewcvs.cgi/trunk/docs/?root=linux-bg
Ако използвате Subversion може да ги свалите с командата: svn checkout --username developername https://svn.openfmi.net/linux-bg/trunk/docs/
Станете част от историята![]
Тези от вас които първи ни изпратят работеща нова тема ще влезнат в историята на сайта (вижте файла History.txt в тази директория). Естествено темите които ни допаднат и/или бъдат одобрение от почитателите на сайта, ще станат част от приложението.
Това е - очакваме Ви да ни пишете на адрес: email:design@linux-bg.org
Сайтове създадени на базата на LBG[]
Некомерсиални