<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های SMAH1</title>
        <link>https://virgool.io/feed/@SMAH1</link>
        <description>یک برنامه نویس هستم.البته به دنیای رایانه و حواشی آن و همینطور فناوری بسیار علاقه دارم.</description>
        <language>fa</language>
        <pubDate>2026-06-24 19:29:23</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/191041/avatar/ic2CRa.png?height=120&amp;width=120</url>
            <title>SMAH1</title>
            <link>https://virgool.io/@SMAH1</link>
        </image>

                    <item>
                <title>چند ترفند Linq</title>
                <link>https://virgool.io/@SMAH1/%DA%86%D9%86%D8%AF-%D8%AA%D8%B1%D9%81%D9%86%D8%AF-linq-rz5h6lxrivqr</link>
                <description>سالهاست که دات نت با استفاده از Linq برنامه‌نویسی را ساده‌تر کرده است. در اینجا به چند ترفند که ممکن است تاکنون استفاده نکرده باشید می‌پردازیم. البته قرار نیست به مکانیزم و جزئیات بپردازیم. بیشتر به عنوان یادآوری و یا یک استفاده «جالب» به آن نگاه کنید.چند ترفند Linqایجاد آرایه با مقدار اولیهفرض کنید می خواهید یک آرایه ده عضوی از نوع int با مقدار اولیه  5 بسازید. در حالت سنتی شما ابتدا آرایه را به طول مورد نظر می سازید و بعد یک حلقه برای مقدار دهی اولیه در نظر می گیرید. ولی با linq به سادگی زیر است:int[] array = Enumerable.Repeat(0, 10).Select(x =&gt; 5).ToArray();حتی اگر بخواهید یک ارایه از یک نمونه کلاس بسازید هم کافیست به جای 5 عبارت new MyClass() استفاده شود. با کمی تغییر می توانید بسیاری از مقداردهی‌های اولیه مدنظر را پیاده سازی کنید.مثلا اگر بخواهید یک مجموعه ده عضوی از اعداد تصادفی بین 0 تا 100 ایجاد کنید داریم:Random rnd = new Random();
int[] array = Enumerable.Repeat(0, 10).Select(x =&gt; rnd.Next(0, 100)).ToArray();دقت کنید که در این مجموعه ممکن است عدد تکراری داشته باشید.یا برای ایجاد یک رشته تصادفی از کاراکترهای مورد نظر داریم:Random rnd = new Random();
char[] characters = &amp;quot0123456789ABCDEF&amp;quot.ToCharArray();
var str = string.Join(null, Enumerable.Repeat(0, 10).Select(x =&gt; characters[rnd.Next(0, characters.Length)]).ToArray());ایجاد یک مجموعه تصادفی غیر تکراریفرض کنید می خواهید یک ارایه ده عضوی از اعداد 0 تا 9 به صورت تصادفی داشته باشد. به عبارت دیگر هر یک از اعداد مذکور فقط یک بار تکرار شده باشد.Random rnd = new Random();
var randomSeq = Enumerable.Range(0, 10)
                .Select(i =&gt; new { rnd = rnd.Next(), data = i })
                .OrderBy(x =&gt; x.rnd)
                .Select(x =&gt; x.data)
                .ToArray();همچنین اگر بخواهید یک آرایه مثلا سه عضوی از اعداد تصادفی بین 0 تا 9 بدون تکرار داشته باشید، کافیست از take(3) استفاده کنید یعنی:Random rnd = new Random();
var randomSeq = Enumerable.Range(0, 10)
                .Select(i =&gt; new { rnd = rnd.Next(), data = i })
                .OrderBy(x =&gt; x.rnd)
                .Select(x =&gt; x.data)
                .Take(3)
                .ToArray();فهرست تمام زیر مجموعه های یک مجموعهکد زیر نیز تمام زیر مجموعه‌های آرایه‌ی arr را برای شما استخراج می کند:char[] arr = { &#039;A&#039;, &#039;B&#039;, &#039;C&#039;, &#039;D&#039; };
IEnumerable&lt;IEnumerable&lt;char&gt;&gt; subsets = from item in Enumerable.Range(0, 1 &lt;&lt; 
arr.Length)
                select
                    from i in Enumerable.Range(0, arr.Length)
                    where (item &amp; (1 &lt;&lt; i)) != 0
                    select arr[i];که خروجی چیزی شبیه این است:ABABCACBCABCDADBDABDCDACDBCDABCD</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Fri, 13 Jan 2023 14:58:01 +0330</pubDate>
            </item>
                    <item>
                <title>چرا wget و curl درست کار نمی کنند؟</title>
                <link>https://virgool.io/@SMAH1/%DA%86%D8%B1%D8%A7-wget-%D9%88-curl-%D8%AF%D8%B1%D8%B3%D8%AA-%DA%A9%D8%A7%D8%B1-%D9%86%D9%85%DB%8C-%DA%A9%D9%86%D9%86%D8%AF-bvpntiw9mw9b</link>
                <description>چرا wget و curl درست کار نمی کنند؟شرح ماجراچند روزی است با چیزه عجیبی روبرو شدم.یک نسخه تازه از Debian 11 روی سرور نصب کردم. هنگام دانلود از http همه چیز درست است ولی در هنگام دانلود از https مشکلی وجود دارد. با اینکه به سایت وصل می شود و ظاهرا همه چیز خوب پیش می رود، ولی عملا دریافت داده‌ای رخ نمی‌دهد و مانند این است که نرم افزار hang کرده باشد!اول فکرم شاید درست نصب نشده است ولی برای بار دوم و سوم که اینطور شد (روی سرور واقعی و Virtualbox تست کردم) مطمئن شدم یه مشکلی هست.نمونه خروجی را می‌توانید ببینید:عدم دریافت داده توسط wget در debian 11با خودم فکر کردم شاید مشکلی اینترنت ماست و ... برای همین ubuntu 22.04 را در Virtualbox نصب کردم. همه چیز درست بود و دانلود (حتی از https) درست انجام می شود.دریافت داده توسط wget در ubuntu 22.04روی ویندوز در wsl یک لینوکس ubuntu 18.04 دارم که آن را هم تست کردم و با کمال تعجب دیدم که در آن هم مثل دبیان 11 دانلود https انجام نمیشود.عدم دریافت داده توسط wget در ububtu 18.04بر روی Debian 10 تست کردم ولی همه چیز خوب پیش میرود و اصلا مشکلی دیده نمیشود!!!خلاصه مشکلدر دو سیستم لینوکسی (Debian 11 و ubuntu 18.04 درون ویندوز) با اینکه دریافت داده از http بدون مشکل رخ می دهد ولی علیرغم اتصال به سرور در https دریافت داده انجام نشده و به نظر می رسد که نرم افزار متوقف شده است. برای نمونه خروجی نرم افزار به این شکل است و هیچ پشیرفتی ندارد.root@DESKTOP-D3P6QPM:~# update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
root@DESKTOP-D3P6QPM:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.6 LTS
Release:        18.04
Codename:       bionic
root@DESKTOP-D3P6QPM:~# wget https://google.com/
--2022-10-24 08:32:23--  https://google.com/
Resolving google.com (google.com)... 142.250.185.110, 2a00:1450:4001:80f::200e
Connecting to google.com (google.com)|142.250.185.110|:443... connected.در دو سیستم لینوکسی دیگر (Debian 10 و ubuntu 22.04) این دو کاملا درست عمل می کنند یعنی دریافت داده و دانلود چه در http و چه در https به خوب انجام می پذیرد.پی‌نوشت1) همه تست ها در Virtualbox بر روی یک ماشین انجام شده است. یعنی همه تنظیمات و .. حفظ شده است و فقط هارد مجازی آن تغییر کرده است.2) تمام توزیع های یاد شده بروز شده بودند (apt update &amp;&amp; apt upgrade).3) از هیچ proxy خاصی استفاده نمی شود.4) هیچ تنظیم خاصی (firewall و ...) انجام نشده است.5) به غیر از ubuntu 18.04، در بقیه موارد بلافاصله بعد از نصب سیستم عامل این تست انجام شده است.6) همه این سیستم ها درون یک شبکه‌اند و از یک اینترنت استفاده می کنند.7) برای دیدن بهتر تصاویر آن‌ها را یک tab جدید باز کنید.آیا کسی چیزی در این رابطه میدونه؟</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Wed, 26 Oct 2022 19:54:51 +0330</pubDate>
            </item>
                    <item>
                <title>Angular + puppeteer for (github action)</title>
                <link>https://virgool.io/@SMAH1/angular-puppeteer-for-github-action-sqo6yxjg1e1t</link>
                <description>همانطور که می‌دانید برای اجرای  تست‌های واحد در Angular از jasmine و karma استفاده می‌شود. برای این منظور در پوشه پروژه یک ترمینال باز کرده و دستور زیر را وارد کنید:npm run testکه خروجی آن تصویر زیر است:اجرای تست‌ها در یک پروژه‌ی Angularحالا در مروگر اینترنت صفحه زیر را باز کنید:http://localhost:9876/که صفحه زیر را خواهد دید:نتیجه اجرای تست‌ها در مرورگردر این فرآیند، karma یک وب سرور راه‌اندازی کرده و با هر تغییری در پروژه،فرآیند build پروژه دوباره انجام شده و تمام تست‌ها نیز انجام خواهد شد و نتیجه را در پنجره‌ی مروگر خواهید دید. اما گاهی اوقات لازم است که فرآیند انجام تست‌ها بدون حضور وضعیت live ایجاد شده توسط فرآیند بالا انجام شود.برای نمونه هنگامی که شما برای یک پروژه در github action یک رول تست نوشته‌اید، باید فرآیند تست انجام شده (و پایان یابد) و نتیجه در خط فرمان مشخص گردد تا گردش کار (با توجه به موفق بودن تست یا عدم موفقیت آن) ادامه یابد.اینجاست که puppeteer وارد می‌شود.این کتابخانه تحت nodejs به شما اجازه اجرای یک chrome یا chromium و کنترل آن را می‌دهد.حتی می‌توانید این مرورگر را بدون هیچ گونه UI اجرا کنید (اصطلاحا headless) و دستورات مورد نظر را برای مرورگر باز شده ارسال کنید.مثلا یک آدرسی را باز کند یا فیلد هایی را پر کند و ...من در اینجا از توضیح جزئیات این کتابخانه صرف نظر می‌کنم و پیشنهاد می‌کنم برای اطلاعات بشتر به صفحه خوده این کتابخانه مراجعه کنید.اما قبل از اینکه به کار اصلی بپردازیم، یک توضیح کوچک در مورد puppeteer بدهم. در موقع نصب این کتابخانه، دو کار انجام می‌شود:نخست اینکه زیر ساخت مورد نیاز برای دست‌اندازی به یک مرورگر chromium base فراهم می‌شوددوم اینکه آخرین نسخه از مرورگر chrome از سرورهای گوگل دانلود شده و در یک مسیر مشخص برای فراخوانی توسط puppeteer ذخیره می‌شود.از آنجایی که گوگل طبق معمول ایران را از دسترسی آزاد به اطلاعات فناوری تحریم کرده است، فرآیند دانلود این بسته ممکن است شکست بخورد و حتما باید بر روی سیستم شما فیلترشکن یا تحریم‌شکن برای دانلود موجود باشد.و البته با هر بار نصب puppeteer نیز باید حدود 150 مگا بابت نیز دانلود کند که اگر از حجمش بگذریم از زمانش نمی‌توان چشم پوشی کرد!اما یک نسخه سبک تر از puppeteer موجود است که به آن puppeteer-core می‌گویند که فقط قسمت اول را انجام می‌دهد و بخش دوم را به عهده‌ی مرورگر موجود بر روی سیستم می‌گذارد که البته باید آن را config کنید (لطفا مستندات مربوطه را خودتان مطالعه کنید)برای پروژه های محلی استفاده از puppeteer-core کافیست ولی اگر می‌خواهد از github action استفاده کنید، حتما باید از puppeteer استفاده نماید.برای اینکه در هر بار نصب puppeteer بر روی پروژه‌ی سیستم اقدام به دانلود و نصب مرورگر نکند نیز راهی وجود داد!عدم دانلود مرورگر در هنگام نصب puppeteerچون من از ubuntu استفاده می‌کنم برای همین راه حل‌ها هم مربوط به این سیستم است ولی برای سایر توزیع‌های لینوکس نیز صادق است.همچنین برای سیستم عامل‌های دیگر نیز می‌توانید راه حل را (با کمی جستجو) پیدا کنید.دو دستور زیر را در ترمینال بزنید:npm config set puppeteer_skip_chromium_download true
npm config set puppeteer_excutable_path /snap/bin/chromiumاین دو دستور باعث می‌شود که فایل ~/.npmrcبا محتویات زیر ایجاد شود:puppeteer_skip_chromium_download=true
puppeteer_executable_path=/snap/bin/chromiumالبته می‌توانید این فایل را هم مستقیما ویرایش کنید!دستور اول صریحا از puppeteer می‌خواهد که دانلود را انجام ندهد و دستور دوم نیز نحوه اجرای کروم روی سیستم را نشان می‌هد.نصب و پیکربندی puppeteer بر روی پروژه Angularابتدا بسته را نصب کنید یعنی در پوشه پروژه ترمینال را باز کرده و بزنید:npm install puppeteer --save-devسپس فایل package.json مرتبط با پروژه را باز کرده و خط زیر را در بخش scripts اضافه کنید:&amp;quottest:headless&amp;quot: &amp;quotng test --no-watch --no-progress --browsers=ChromeHeadlessCI&amp;quot,در گام سوم فایل karma.conf.js را باز کنید .در این فایل باید دو قسمت را ویرایش کنید.اول اینکه خط زیر را در ابتدای فایل وارد کنیدprocess.env.CHROME_BIN = require(&#039;puppeteer&#039;).executablePath();در واقع این خط محل نصب فایل مرورگر مورد نظر را به متغیر محیطی CHROME_BIN نسبت می‌دهد تا فرآیند اجرا به درستی انجام شود.دوم اینکه خط زیر ار پیدا کنیدbrowsers: [&#039;Chrome&#039;],و آن را با این جانشین کنیدbrowsers: [&#039;ChromeHeadlessCI&#039;],
customLaunchers: {
    ChromeHeadlessCI: {
    base: &#039;ChromeHeadless&#039;,
    flags: [&#039;--no-sandbox&#039;]
    }
},و تمام.حالا با دستور npm run test:headlessچیزی شبیه تصویر زیر را مشاهده می‌کنید.اجرای تست‌ها در حالت headlessکد کامل فایل package.json{
&amp;quotname&amp;quot: &amp;quottestapp&amp;quot,
&amp;quotversion&amp;quot: &amp;quot0.0.0&amp;quot,
&amp;quotscripts&amp;quot: {
&amp;quotng&amp;quot: &amp;quotng&amp;quot,
&amp;quotstart&amp;quot: &amp;quotng serve&amp;quot,
&amp;quotbuild&amp;quot: &amp;quotng build&amp;quot,
&amp;quottest&amp;quot: &amp;quotng test&amp;quot,
&amp;quottest:headless&amp;quot: &amp;quotng test --no-watch --no-progress --browsers=ChromeHeadlessCI&amp;quot,
&amp;quotlint&amp;quot: &amp;quotng lint&amp;quot,
&amp;quote2e&amp;quot: &amp;quotng e2e&amp;quot
},
&amp;quotprivate&amp;quot: true,
&amp;quotdependencies&amp;quot: {
&amp;quot@angular/animations&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/common&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/compiler&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/core&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/forms&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/platform-browser&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/platform-browser-dynamic&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@angular/router&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quotrxjs&amp;quot: &amp;quot~6.6.0&amp;quot,
&amp;quottslib&amp;quot: &amp;quot^2.0.0&amp;quot,
&amp;quotzone.js&amp;quot: &amp;quot~0.11.3&amp;quot
},
&amp;quotdevDependencies&amp;quot: {
&amp;quot@angular-devkit/build-angular&amp;quot: &amp;quot~0.1102.5&amp;quot,
&amp;quot@angular/cli&amp;quot: &amp;quot~11.2.5&amp;quot,
&amp;quot@angular/compiler-cli&amp;quot: &amp;quot~11.2.6&amp;quot,
&amp;quot@types/jasmine&amp;quot: &amp;quot~3.6.0&amp;quot,
&amp;quot@types/node&amp;quot: &amp;quot^12.11.1&amp;quot,
&amp;quotcodelyzer&amp;quot: &amp;quot^6.0.0&amp;quot,
&amp;quotjasmine-core&amp;quot: &amp;quot~3.6.0&amp;quot,
&amp;quotjasmine-spec-reporter&amp;quot: &amp;quot~5.0.0&amp;quot,
&amp;quotkarma&amp;quot: &amp;quot~6.1.0&amp;quot,
&amp;quotkarma-chrome-launcher&amp;quot: &amp;quot~3.1.0&amp;quot,
&amp;quotkarma-coverage&amp;quot: &amp;quot~2.0.3&amp;quot,
&amp;quotkarma-jasmine&amp;quot: &amp;quot~4.0.0&amp;quot,
&amp;quotkarma-jasmine-html-reporter&amp;quot: &amp;quot^1.5.0&amp;quot,
&amp;quotprotractor&amp;quot: &amp;quot~7.0.0&amp;quot,
&amp;quotpuppeteer&amp;quot: &amp;quot^8.0.0&amp;quot,
&amp;quotts-node&amp;quot: &amp;quot~8.3.0&amp;quot,
&amp;quottslint&amp;quot: &amp;quot~6.1.0&amp;quot,
&amp;quottypescript&amp;quot: &amp;quot~4.1.5&amp;quot
}
}و کد کامل فایل karma.conf.js// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
process.env.CHROME_BIN = require(&#039;puppeteer&#039;).executablePath();
module.exports = function (config) {
config.set({
basePath: &#039;&#039;,
frameworks: [&#039;jasmine&#039;, &#039;@angular-devkit/build-angular&#039;],
plugins: [
require(&#039;karma-jasmine&#039;),
require(&#039;karma-chrome-launcher&#039;),
require(&#039;karma-jasmine-html-reporter&#039;),
require(&#039;karma-coverage&#039;),
require(&#039;@angular-devkit/build-angular/plugins/karma&#039;)
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require(&#039;path&#039;).join(__dirname, &#039;./coverage/testapp&#039;),
subdir: &#039;.&#039;,
reporters: [
{ type: &#039;html&#039; },
{ type: &#039;text-summary&#039; }
]
},
reporters: [&#039;progress&#039;, &#039;kjhtml&#039;],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: [&#039;ChromeHeadlessCI&#039;],
customLaunchers: {
ChromeHeadlessCI: {
base: &#039;ChromeHeadless&#039;,
flags: [&#039;--no-sandbox&#039;]
}
},
singleRun: false,
restartOnFileChange: true
});
};</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Sat, 03 Apr 2021 15:06:05 +0430</pubDate>
            </item>
                    <item>
                <title>الگوریتم یافتن وارون ضربی به روش بسط اقلیدسی</title>
                <link>https://virgool.io/@SMAH1/%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85-%DB%8C%D8%A7%D9%81%D8%AA%D9%86-%D9%88%D8%A7%D8%B1%D9%88%D9%86-%D8%B6%D8%B1%D8%A8%DB%8C-%D8%A8%D9%87-%D8%B1%D9%88%D8%B4-%D8%A8%D8%B3%D8%B7-%D8%A7%D9%82%D9%84%DB%8C%D8%AF%D8%B3%DB%8C-mo8imbtfojvv</link>
                <description>تصمیم گرفتم کمی در مورد الگوریتم یافتن وارون پیمانه‌ای یا وارون ضربی بنویسم.من فرض  می‌کنم که شما در مورد «همنهشتی» و «باقیمانده در پیمانه» اطلاع دارید.قبل از ورود به بحث یک نمونه‌ی کاربرد «یافتن وارون ضربی» را مثال می‌زنم.در الگوریتم RSA،که برای رمزنگاری با کلید خصوصی و عمومی به کار می‌رود،پس از مشخص کردن کلید عمومی شامل دو مقدار n و e، باید کلید خصوصی رو محاسبه کنید که همان وارون ضربی e در پیمانه‌ی φ(n) است.قبل از اینکه در موردالگوریتم بنویسم، کمی در مورد مفهوم وارون ضربی اطلاعات کسب کنیم.کمی ریاضیتعریف: وارون ضربی e به پیمانه‌ی n  برابر عدد صحیح مثبت d است اگر  d*e ≡ 1 (mod n)به عبارت فارسی، اگر عدد e رو در d ضرب کنیم، مقدار آن به پیمانه‌ی n با یک برابر است.به عبارت دیگر باقیمانده‌ی حاصلضرب e*d  به n برابر یک است.البته تمام اعداد ممکن برای e دارای وارون ضربی نیستند! شرط «لازم و کافی» برای اینکه e دارای وارون ضربی به پیمانه‌ی n باشد این است که این دو عدد نسبت به هم اول باشند.در نتیجه مثلا عدد ۶ وارون ضربی برای پیمانه‌ی ۳۳ ندارد (چون ب‌م‌م آنها ۳ است) ولی عدد ۱۰ می‌تواند وارون ضربی در پیمانه‌ی ۳۳ داشته باشد.جالب است بدانید که وارون ضربی عدد ۱۰ به پیمانه‌ی ۳۳، خوده عدد ۱۰ است.یعنی ۱۰*۱۰ که ۱۰۰ می‌شود، دارای باقیمانده‌ی ۱ به پیمانه‌ی ۳۳ است.توصیف الگوریتم بسط اقلیدسی برای یافتن وارون ضربیفرض کنید در دو فرمول زیر:r = r1 - q * r2t = t1 - q * t2		مقادیر r1،r2،t1،t2 معلوم باشند و هدف یافتن مقادیر q و r و t است (به همین ترتیب نوشته شده یافته خواهند شد).فرض کنید می‌خواهیم وارون ضربی e به پیمانه‌ی n را محاسبه کنیم، داریم:گام اول) مقدار دهی اولیه متغیرهای معلوم: r1=n و r2=e و t1=0 و t2=1گام دوم) اگر مقدار r2 صفر است، مقدار t1 را به عنوان وارن ضربی معرفی کرده و الگوریتم پایان می‌یابد.گام سوم)‌ مقدار q و r که به ترتیب خارج قسمت و باقیمانده حاصل تقسیم r1 به r2 هستند را محاسبه کنید (فرمول اول)گام چهارم) مقدار t را با توجه به مقدار محاسبه شده‌ی q حساب کنید (فرمول دوم)گام پنجم)‌ مقادیر r2 و r و t2 و t را به ترتیب به مقادیر r1 و r2 و t1 و t2 منتقل کنید.گام ششم) به گام دوم بروید.اگر نوشته‌های فوق کمی پیچیده به نظر می‌رسد، اصلا نترسید! در اینجا با مثال نمونه‌ای را با هم حل می‌کنیم.یک نمونه بسط اقلیدسیمی‌خواهیم وارون ضربی ۷ به پیمانه‌ی ۱۶۰ را محاسبه کنیم.پیشنهاد می‌کنم که جدول زیر را بکشید:به چینش ستون‌ها توجه کنید. فرمول‌ها برای راحتی در بالای جدول نشان داده شده‌اند.البته جدول را هم مقدار دهی اولیه کرده‌ایم و اعداد با رنگ قرمز مقادیر اولیه (مطابق با گام اول) هستند.سپس عدد ۱۶۰ را به ۷ تقسیم می‌کنیم که خارج قسمت ۲۲ است:مقدار دهی اولیه جدولو باقیمانده آن ۶ است:حالا با داشتن مقدار q می‌توانیم مقدار t را (مطابق فرمول دوم) محاسبه کنیم(t = ۰ - ۲۲ * ۱ = -۲۲):پس از تکمیل این ردیف به سراغ ردیف بعد می‌رویم.برای این کار باید برخی مقادیر ردیف اول را به ردیف دوم منتقل کنیم:مطابق عملیات‌هایی که برای یافتن q و r و سپس t برای ردیف یک انجام داده‌ایم، به تکمیل این ردیف می‌پردازیم:همین طور هر ردیف را پر کرده و محاسبه می‌کنیم تا جایی که r2 صفر شود:پس میتوانیم مقدار t1 را به عنوان وارون ضربی مشخص کنیم:وضعیت نهایی جدولدر نتیجه وارون ضربی ۷ به پیمانه‌ی ۱۶۰ عدد ۲۳ است.فرآیند محاسبات بالا را در تصویر متحرک زیر می‌توانید ببینید:نحوه محاسبه وارون ضربی عدد ۷ به پیمانه ۱۶۰نکته مهمدر ردیف آخر (که r2 صفر شده است) مقدار t2 به عدد پیمانه‌ی فرض شده (در اینجا ۱۶۰) بخش‌پذیر است.تاکید می‌کنم که این نکته همواره برقرار است. یعنی همیشه در آخرین ستون که عدد t1 را به عنوان وارون ضربی معرفی می‌کنید، عدد t2 «باید» به عدد n شما بخش‌پذیر باشد.از این نکته برای تایید محاسبات می‌توانید استفاده کنید. یعنی اگر r2 صفر شد و t2 به n بخش‌پذیر «نبود»، مطمئن باشید که در محاسبات «اشتباه» کرده‌اید.یک نمونه‌ی دیگرفرض کنید می‌خواهیم وارون ضربی عدد ۵ به پیمانه‌ی ۱۰۰۸ را محاسبه کنیم. نتیجه محاسبات را در تصویر زیر مشاهده می‌کنید:نحوه محاسبه وارون ضربی عدد ۵ به پیمانه ۱۰۰۸همانطور که می‌بیند وارون ضربی محاسبه شده عدد «منفی» است. البته این عدد درست است ولی همواره ما مقدار مثبت آن را لازم داریم و چون این عدد در پیمانه‌ی ۱۰۰۸ محاسبه شده است پس برای مثبت کردن آن کافیست مقدار ۱۰۰۸ را به عدد منفی بیافزاییم یعنی:d = ۱۰۰۸ +(- ۴۰۳)= ۶۰۵پس وارون ضربی عدد ۵ به پیمانه‌ی ۱۰۰۸ مقدار ۶۰۵ است.نکته تکمیلیبر اساس قضیه اویلر، اگر n و e نسبت به هم اول باشند و d وارون ضربی e به پیمانه‌ی n باشد، می‌توان نتیجه گرفت:محاسبه وارون ضربی بر اساس قضیه اویلردر نتیجه به این روش هم می‌توان وارون ضربی را محاسبه نمود.توجه کنید که هر کدام از روش‌های بالا در پیاده سازی برنامه نویسی، مزایا و معایب خود را دارند.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Thu, 04 Feb 2021 14:20:36 +0330</pubDate>
            </item>
                    <item>
                <title>نحوه‌ی قانون گذاری در ایران</title>
                <link>https://virgool.io/@SMAH1/%D9%86%D8%AD%D9%88%D9%87%DB%8C-%D9%82%D8%A7%D9%86%D9%88%D9%86-%DA%AF%D8%B0%D8%A7%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%A7%DB%8C%D8%B1%D8%A7%D9%86-tgydx5qy0rcj</link>
                <description>این نوشته در مورد قانون گذاری در ایران است و ربطی به مجلس فعلی ندارد!فرض کنید مجلس بخواهد در مورد چراغ راهنمایی (همان سبز و زرد و قرمز) قانون بنویسد.متن قانون به این شرح است:ماده اول: تمام وسایل نقلیه می توانند با رعایت شرایط قانونی در هنگام سبز بودن چراغ، از تقاطع عبور نمایند.ماده دوم: تمام وسایل نقلیه در هنگام زرد بودن چراغ، اگر در تقاطع هستند به سرعت آن را تخلیه کنند و اگر در تقاطع قرار ندارد به مانندن چراغ قرمز با آن رفتار نمایند.ماده سوم: در هنگام چراغ قرمز، تمام وسایل نقلیه باید پشت خط ایست،توقف نمایند.تبصره یک: چنانچه ماشین اورژانس در حین خدمت به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره دو: چنانچه ماشین پلیس در حین خدمت به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره سه: چنانچه ماشین آتش نشانی در حین خدمت به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره چهار: چنانچه ماشین پست در حین خدمت به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره پنج: چنانچه ماشین حاوی یک فرد مریض اورژانسی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره شش: چنانچه ماشین عملیات  دولتی (نظیر برق و آب و ...) در حین خدمت به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره هفت: چنانچه ماشین رئيس جمهور یا وزیر و وکیل به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره هشت: چنانچه ماشین حاوی یک فرد سالمند به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره نه: چنانچه ماشین قرمز رنگ به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره ده: چنانچه ماشینی که از ماشین سمت چپ بلند تر بود و از ماشین سمت راست کوتاه تر بود به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره یازده: چنانچه ماشین حاوی یک فرد عصبی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره .... : به پاس ارج نهادن به مقام والای معلم چنانچه ماشین وی به تقاطع رسید و چراغ قرمز بود،  از آن عبور کند.تبصره .... : به پاس ارج نهادن به مقام والای قاضی چنانچه ماشین وی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره .... : به پاس ارج نهادن به مقام والای کارگر چنانچه ماشین وی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره .... : به پاس ارج نهادن به مقام والای مادر چنانچه ماشین وی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره .... : برای حمایت از اقشار ضعیف چنانچه ماشین وی به تقاطع رسید و چراغ قرمز بود، می تواند از آن عبور کند.تبصره .... : ماشین های بالای صد میلیون تومان می تواند از چراغ قرمز عبور کنند و در عوض جریمه بدهند.....بگذریم که در ماده‌ی اول عنوانی کلی مثل «رعایت شرایط قانونی» وجود دارد.ولی در نهایت یک قانون پر از استثنا که حتما یکی از این تبصره ها شامل حال افراد می شود و عملا همه از چراغ قرمز عبور می کنند.در واقع یک قانون خوب رو در عمل بی ارزش می کند.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Sat, 25 Jul 2020 16:12:23 +0430</pubDate>
            </item>
                    <item>
                <title>اتصال به یک سرور توسط PPTP و مدیریت ترافیک آن</title>
                <link>https://virgool.io/@SMAH1/%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D8%A8%D9%87-%DB%8C%DA%A9-%D8%B3%D8%B1%D9%88%D8%B1-%D8%AA%D9%88%D8%B3%D8%B7-pptp-%D9%88-%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%AA%D8%B1%D8%A7%D9%81%DB%8C%DA%A9-%D8%A2%D9%86-gdysdbey31uy</link>
                <description>برای نرم‌افزار یکی از مشتریان ما (به نام «کرمان جنوب») مشکلی پیش آمد و من باید برای حل آن اقدام می‌کردم.ولی دو مشکل وجود داشت:من الان در وضعیت دورکاری هستم.برای اتصال به سرور آنها باید حتما از IP شرکت متصل شوم.برای رفع این مشکل یک راه حل وجود داشت: کافی بود من به سرور داخل شرکت وصل بشوم و از آنجا یک Connection به سرور مشتری بزنم.یعنی چیزی شبیه این:اطلاعات سرور شرکت و سرور مشتریسرور شرکت دارای سیستم عامل Debian 10 می‌باشد.قبلا در آن OpenVPN نصب کرده بودم و می‌توانستم به آن متصل شود و IPای از بازه‌ی 192.168.10.0/24 دریافت کنم.همچنین سرور دارای یک کارت شبکه به نام enp63s0 است که IP آن 192.168.1.150 (در شبکه داخلی شرکت که Gateway آن 192.168.1.1 است) می‌باشد.برای اتصال به سرور مشتری اطلاعات زیر در دسترس است:IP:       203.0.113.100
Type:     PPTP
Username: myuser
Password: mypassدر صورت برقراری اتصال،IPهای دریافتی از سرور مشتری به این شرح است:Local  IP address 10.100.2.181
Remote IP address 10.100.2.1و البته من بعد از آن باید Remote Desktop به 10.180.36.150  بزنم تا بتوانم به مقصودم برسم.در تصاویر زیر نحوه اتصال به این سرور را در ویندوز ملاحظه می‌کنید:نصب PPTP و پیکربندی اتصالنصب و راه اندازی‌ PPTP در همه سیستم‌های لینوکسی شبیه هم است.برای نصب در Debian باید بسته‌ی pptp-linux را نصب کنید.البته نام این بسته در توزیع های دیگر متفاوت است.مثلا در Arch به نام pptpclient و در fedora به نام pptp شناخته می‌شود.apt install pptp-linuxحالا فایل /etc/ppp/chap-secrets را ویرایش می‌کنیم و نام کاربری، کلمه عبور و IP را در آن وارد می‌کنیم:nano /etc/ppp/chap-secretsحالا نوبت فایل /etc/ppp/options.pptp است.چنانچه نیاز است مقادیر آن را ویرایش کنید (من نیازی به ویرایش نداشتم و از همان تنظیمات پیشفرض آن استفاده کردم).مقادیر موجود به این قرار است:nano /etc/ppp/options.pptplock
noauth
refuse-pap
refuse-eap
refuse-chap
refuse-mschap
nobsdcomp
nodeflateسپس نوبت به ساخت Connection می‌رسد.برای این کار یک فایل در مسیر /etc/ppp/peers به نام south-kerman ایجاد کنید:nano /etc/ppp/peers/south-kermanو مقادیر زیر را در آن وارد کرده و ذخیره نمایید:pty &amp;quotpptp 203.0.113.100 --nolaunchpppd&amp;quot
name myuser
remotename PPTP
require-mppe-128
file /etc/ppp/options.pptp
ipparam south-kermanتوجه کنید که با توجه به مقادیر وارد شده در chap-secrets هنگام اتصال توسط south-kerman،کلمه عبور به صورت اتوماتیک از این فایل دریافت و اعمال می‌گردد.حالا همه چیز تمام است.کافیست متصل شوید.نحوه‌ی اتصالقبل از بحث در مورد اتصال بهتر است همواره لاگ اتصال به سیستم را به صورت آن لاین بررسی کنیم.این کار می‌تواند توسط دستور زیر رخ دهد.البته حتما به یاد داشته باشید که این دستور را در پنجره‌ی دیگری وارد کنید تا هنگام اتصال بتوانید لاگ‌های ایجاد شده را ببینید.tail -n 0 -f  /var/log/syslog | grep &#039;ppp\|PPP\|pptp&#039;و برای اتصال داریم:pon south-kermanو در لاگ:May 31 17:01:49 MT-SERVER pppd[806]: pppd 2.4.7 started by smah1, uid 0
May 31 17:01:49 MT-SERVER kernel: [  136.098669] PPP generic driver version 2.4.2
May 31 17:01:49 MT-SERVER pptp[810]: anon log[main:pptp.c:353]: The synchronous pptp option is NOT activated
May 31 17:01:49 MT-SERVER pppd[806]: Using interface ppp0
May 31 17:01:49 MT-SERVER pppd[806]: Connect: ppp0 &lt;--&gt; /dev/pts/2
May 31 17:01:49 MT-SERVER pptp[818]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 1 &#039;Start-Control-Connection-Request&#039;
May 31 17:01:49 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:781]: Received Start Control Connection Reply
May 31 17:01:49 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:815]: Client connection established.
May 31 17:01:50 MT-SERVER pptp[818]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 7 &#039;Outgoing-Call-Request&#039;
May 31 17:01:50 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:900]: Received Outgoing Call Reply.
May 31 17:01:50 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:939]: Outgoing call established (call ID 15306, peer&#039;s call ID 9104).
May 31 17:02:10 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:977]: Call disconnect notification received (call id 15306)
May 31 17:02:10 MT-SERVER pptp[818]: anon log[ctrlp_disp:pptp_ctrl.c:830]: Received Stop Control Connection Request.
May 31 17:02:10 MT-SERVER pptp[818]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 4 &#039;Stop-Control-Connection-Reply&#039;
May 31 17:02:10 MT-SERVER pptp[818]: anon log[callmgr_main:pptp_callmgr.c:269]: Closing connection (shutdown)
May 31 17:02:10 MT-SERVER pptp[818]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 12 &#039;Call-Clear-Request&#039;
May 31 17:02:10 MT-SERVER pptp[818]: anon log[call_callback:pptp_callmgr.c:84]: Closing connection (call state)
May 31 17:02:10 MT-SERVER pppd[806]: Modem hangup
May 31 17:02:10 MT-SERVER pppd[806]: Connection terminated.
May 31 17:02:10 MT-SERVER pppd[806]: Exit.همانطور که ملاحظه می‌کنید،ارتباط با سرور برقرار می‌شود (Outgoing call established) ولی بعد از حدود 20 ثانیه فرآیند Disconnect شروع شده و ارتباط پایان می‌یابد و سیستم IP هم دریافت نمی‌کند.پس یعنی مشکلی وجود دارد!رفع مشکلبا کمی جستجو در اینترنت متوجه شدم که برای پایدار نگه داشتن اتصال نیاز به بارگذاری ماژول nf_conntrack_pptp دارم.برای این کار در خط فرمان عبارت زیر را وارد کنید:modprobe nf_conntrack_pptpکه البته با Restart سیستم دوباره بارگذاری نمی‌شود.برای بارگذاری در هر بار کافیست فایل زیر را ویرایش (در صورت نیاز ایجاد کنید):nano /etc/modules-load.d/pptp.confو عبارت زیر را به آن بیافزایید:nf_conntrack_pptpتست دوباره اتصالبا دو دستور زیر می‌توانید اتصال را برقرار کنید و یا آن را خاتمه بدهید:pon south-kerman
poff south-kermanو در لاگ خروجی داریم:May 31 17:30:41 MT-SERVER pppd[1706]: pppd 2.4.7 started by smah1, uid 0
May 31 17:30:41 MT-SERVER pppd[1706]: Using interface ppp0
May 31 17:30:41 MT-SERVER pptp[1709]: anon log[main:pptp.c:353]: The synchronous pptp option is NOT activated
May 31 17:30:41 MT-SERVER pppd[1706]: Connect: ppp0 &lt;--&gt; /dev/pts/2
May 31 17:30:41 MT-SERVER pptp[1720]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 1 &#039;Start-Control-Connection-Request&#039;
May 31 17:30:41 MT-SERVER pptp[1720]: anon log[ctrlp_disp:pptp_ctrl.c:781]: Received Start Control Connection Reply
May 31 17:30:41 MT-SERVER pptp[1720]: anon log[ctrlp_disp:pptp_ctrl.c:815]: Client connection established.
May 31 17:30:42 MT-SERVER pptp[1720]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 7 &#039;Outgoing-Call-Request&#039;
May 31 17:30:42 MT-SERVER pptp[1720]: anon log[ctrlp_disp:pptp_ctrl.c:900]: Received Outgoing Call Reply.
May 31 17:30:42 MT-SERVER pptp[1720]: anon log[ctrlp_disp:pptp_ctrl.c:939]: Outgoing call established (call ID 6496, peer&#039;s call ID 9111).
May 31 17:30:42 MT-SERVER pppd[1706]: CHAP authentication succeeded
May 31 17:30:42 MT-SERVER kernel: [ 1869.179509] PPP MPPE Compression module registered
May 31 17:30:42 MT-SERVER pppd[1706]: MPPE 128-bit stateless compression enabled
May 31 17:30:44 MT-SERVER pppd[1706]: local  IP address 10.100.2.181
May 31 17:30:44 MT-SERVER pppd[1706]: remote IP address 10.100.2.1
.........
May 31 17:31:14 MT-SERVER pptp[1720]: anon log[callmgr_main:pptp_callmgr.c:269]: Closing connection (shutdown)
May 31 17:31:14 MT-SERVER pppd[1706]: Terminating on signal 15
May 31 17:31:14 MT-SERVER pptp[1720]: anon log[ctrlp_rep:pptp_ctrl.c:259]: Sent control packet type is 12 &#039;Call-Clear-Request&#039;
May 31 17:31:14 MT-SERVER pptp[1720]: anon log[call_callback:pptp_callmgr.c:84]: Closing connection (call state)
May 31 17:31:14 MT-SERVER pppd[1706]: Connect time 0.5 minutes.
May 31 17:31:14 MT-SERVER pppd[1706]: Sent 0 bytes, received 0 bytes.
May 31 17:31:14 MT-SERVER pppd[1706]: MPPE disabled
May 31 17:31:14 MT-SERVER pppd[1706]: Child process pptp 203.0.113.100 --nolaunchpppd (pid 1708) terminated with signal 15
May 31 17:31:14 MT-SERVER pppd[1706]: Modem hangup
May 31 17:31:14 MT-SERVER pppd[1706]: Connection terminated.
May 31 17:31:14 MT-SERVER pppd[1706]: Exit.این دفعه ظاهرا همه چیز روبراه است و حتی سیستم IP هم دریافت کرده است.شما با زدن دستور زیر می‌توانید ببیند که یک interface شبکه جدید به نام ppp0 اضافه شده است:ip addr showدسترسیبرای بررسی دسترسی کافیست از سه IP زیر ping بگیریم:ping 10.100.2.181
ping 10.100.2.1
ping 10.180.36.150که داریم:به عبارت دیگر با اینکه ارتباط برقرار شده است ولی دسترسی به 10.180.36.150 نداریم!برای بررسی دقیق این مشکل، فرایند route درخواست‌ها را بررسی می‌کنیم:ip -o route get 8.8.8.8
ip -o route get 10.100.2.181
ip -o route get 10.180.36.150که خروجی آن به این شکل است:# ip -o route get 8.8.8.8
8.8.8.8 via 192.168.1.1 dev enp63s0 src 192.168.1.150 uid 0 \    cache# ip -o route get 10.100.2.181
local 10.100.2.181 dev lo src 10.100.2.181 uid 0 \    cache &lt;local&gt;# ip -o route get 10.180.36.150
10.180.36.150 via 192.168.1.1 dev enp63s0 src 192.168.1.150 uid 0 \    cacheکه این خروجی نشان می‌دهد که درخواست‌های 10.180.36.150 به جای ارسال توسط pptp tunnel همچنان بر روی کارت شبکه عادی ارسال می‌شود.نتیجه اینکه، باید به سیستم بگوییم که تمام درخواست‌های روی 10.0.0.0/8 رو بر روی ppp0 (نام همان pptp tunnel) ارسال کند.پس دستور زیر را وارد کنید:ip route add 10.0.0.0/8 via 10.100.2.1 dev ppp0حالا داریم:# ip -o route get 10.180.36.150
10.180.36.150 via 10.100.2.1 dev ppp0 src 10.100.2.181 uid 0 \    cacheکه به این معنی است که اکنون شما می‌توانید از 10.180.36.150 پینگ بگیرید.دسترسی از روی سیستم شخصیحالا به قسمت اصلی ماجرا رسیدیم.از روی سیستم خودم VPN به سرور شرکت ایجاد کرده و IP دریافت شد.حالا از سه IP بالا  ping می‌گیرم:همانطور که می‌بینید به جز 10.100.2.181 (که درون سرور شرکت قرار دارد) به هیچ کدام دسترسی ندارم.پس باید به سرور اعلام کنم که در خواست های من را FORWARD کند.برای این کار ابتدا باید ip forwarding را در سرور فعال کنم.برای این منظور دو راه است.راه اول دستور زیر را بزنید:sysctl -w net.ipv4.ip_forward=1که البته با Reset سیستم به مقدار پیشفرض (یعنی صفر) بر می‌گردد.راه دوم که حالت پایدار است ویرایش فایل زیر است:nano /etc/ufw/sysctl.confو در آن عبارت زیر را فعال کنید:net/ipv4/ip_forward=1بعد از این مرحله باید به firewall اجازه forwarding بین این دو شبکه را بدهیم یعنی:iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o ppp0 -j MASQUERADEکه صریحا این اجازه را بین دو شبکه می‌دهد.در این جا کار تمام می‌شود و ping برای IP سرور مشتری بر روی سیستم شخصی ظاهر می‌شود.ذکر این نکته ضروریست که iptable بعد از reset سیستم به مقادیر پیشفرض برمی‌گردد.پس چنانچه می‌خواهید این تنظیم را پایدار کنید حتما از ufw استفاده کنید.جمع بندیبرای اتصال می‌توانید از توالی دستورات زیر استفاده کنید:pon south-kerman
ip route add 10.0.0.0/8 via 10.100.2.1 dev ppp0
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o ppp0 -j MASQUERADEو برای Diconnect هم دستورات زیر مورد نیاز است:iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o ppp0 -j MASQUERADE
ip route del 10.0.0.0/8 via 10.100.2.1 dev ppp0
poff south-kermanو برای عیب یابی احتمالی شاید دستورات زیر کار ساز باشد:iptables -t nat -L -v
traceroute -4 10.180.36.150
ip addr show
ip route show
route -nو البته اگر می‌خواهید به صورت اتوماتیک ارتباط pptp شما برقرار شود می‌توانید این منبع را مطالعه کنید.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Mon, 01 Jun 2020 18:50:16 +0430</pubDate>
            </item>
                    <item>
                <title>نحوه‌ی Authentication در Postgresql</title>
                <link>https://virgool.io/@SMAH1/%D9%86%D8%AD%D9%88%D9%87%DB%8C-authentication-%D8%AF%D8%B1-postgresql-nkeptskp9jsy</link>
                <description>پایگاه داده‌ی Postgres یکی از قدیمی‌ترین پایگاه‌های داده‌ی Open Source در حوزه‌ی Sql است.با این حال اولین مواجه با آن، حتی برای کسانی که سالها با دیگر پایگاه‌های داده کار کرده‌اند کمی پیچیده (و شاید ترسناک) به نظر می‌رسد.در این مقاله خیلی کوتاه به نحوه‌ی Authentication در این پایگاه داده می‌پردازیم.در Postgresql علاوه بر تعریف کاربران (شامل نام کاربری، کلمه عبور، دسترسی و ..)  باید نحوه‌ی Authentication شدن آنها را نیز مشخص کنید.برای این منظور باید فایل pg_hba.conf را ویرایش کنید.این فایل با توجه به اینکه از سیستم عامل ویندوز و یا شبه یونیکس استفاده می‌کنید، در یکی از مسیرهای زیر قابل دسترسی است:C:\Program Files\PostgreSQL\&lt;VERSION&gt;\data
/etc/postgresql/&lt;VERSION&gt;/mainدر این فایل به یکی از دو شکل زیر نحوه اعتبار سنجی کاربران مشخص می‌شود:local      DATABASE  USER  METHOD  [OPTIONS]
host       DATABASE  USER  ADDRESS  METHOD  [OPTIONS]که در این متن کلماتی که با حروف بزرگ نوشته شده است باید با عبارت مناسب جایگزین شود.حالت اول ،که با کلمه local شروع می‌شود،به این معنی است که برنامه‌ای که می‌خواهد متصل شود بر روی همان سیستم عاملی قرار داد که در حال اجرای Postgresql است.و در حالت دوم،که با کلمه host شروع می‌شود، منظور نحوه‌ی اتصال دیگر سیستم‌ها است که البته باید ADDRESS آن مشخص گردد.برای تعیین آدرس می توانید از دو حالت استفاده کنید.حالت اول استفاده از روش x.x.x.x/y است و در حالت دوم IP و net mask را به صورت جدا معرفی می‌کنیم.عبارت ذیل DATABASE معرف نام پایگاه‌(های) داده است که قرار است تنظیم بر روی آن اعمال شود خواهد بود.از کلمه all برای اشاره به همه پایگاه‌های داده‌ی موجود می‌توانید استفاده کنید.همچنین USER نماینده کاربران مورد نظر است و به مانند قبل از کلمه all برای اشاره به تمام کاربران می‌توانید استفاده کنید.اگر چند کاربر یا پایگاه داده دارید می‌توانید با comma از هم جدایشان نمایید.تا اینجا به این مورد پرداختیم که «از کجا» و «به چه پایگاهی» و «با چه کاربری» قصد اتصال دارند.در ذیل عبارت METHOD نحوه اعتبار سنجی معرفی می‌شود.در صورتی که نیاز به تنظیمات اضافه برای این بخش  باشد ذیل بخش OPTIONS قرار می گیرد.در این مطلب به توضیح مختصر METHODها می‌پردازیم.من METHODها را می توان به دو دست تقسیم می‌کنم.در دسته اول روش‌های زیر قرار هستند:GSSAPI
SSPI
Ident
LDAP
RADIUS
SSL
PAM
BSDکه هر کدام برای اعتبار سنجی نیاز به یک عامل خارجی دارند.مثلا استفاده از RADIUS Server و یا LDAP و یا PAM و ... که محل بحث ما نیستند.برای این موارد می توانید به اسناد Postgres مراجعه کنید.گروه دیگر مقادیر نیز هستند:peer
trust
md5که می‌خواهم در موردشان توضیح دهم.به تنظیمات زیر توجه کنید:local   all             postgres                             trust
host    all             postgres       127.0.0.1/32          trust
host    all             all            127.0.0.1/32          peer
host    all             all            ::1/128               peer
host    all             all            192.168.1.0/24        md5همانطور که می‌بینید در برای اتصال توسط کاربر postgres به همه پایگاه‌های داده از روی سیستم جاری برچسب trust زده شده است.برای اتصال دیگر کاربران از روی سیستم جاری به هر یکی از پایگاه‌های داده برچسب peer داده شده است.و در نهایت برای اتصال کاربران در شبکه جاری هم مقدار md5 مشخص شده است.اما اینها به چه معنی هستند؟مقدار trust هنگامی به کار می رود که شما از Postgresql درخواست می‌کنید که اجازه‌ی ارتباط را بدون هرگونه اعتبارسنجی،بپذیر.این روش ناامن ترین روش ممکن است.در این جا Postgresql هیچ گونه تلاشی برای شناسایی نمی‌کند و کلا Connection String مورد استفاده هیچ اطلاعاتی در مورد کلمه عبور و ... نیاز ندارد.همانطور که می‌بینید این مقدار در مثال بالا برای سیستم جاری ثبت شده و فقط برای یک کاربر معتبر است.برچسب peer فقط در سیستم‌های شبه یونیکس کاربر دارد و به این معنی است که چنانچه کاربر درخواست دهنده‌ی سیستم همنام کاربر Postgresql است، نیاز به اعتبار سنجی نیست.مثلا اگر کاربری در لینوکس خود دارید که نامش ali است و برنامه‌ای که تحت مجوز او اجرا شده است و می خواهد به پایگاه داده وصل شود با این فرض که کاربری به نام ali نیز در Postgresql وجود دارد،این اجازه صادر می‌شود.همانطور که می‌بینید این روش نیز نیاز به اعتبار سنجی دقیق (کلمه عبور) ندارد.با این حال چون سیستم‌های شبه یونیکس خودشان در هنگام login اعتبار سنجی انجام می‌دهند،از روش قبل امن‌تر است.ذکر این نکته ضروریست که چنانچه از برچسب ident بدون هیچ OPTIONS خاصی استفاده کنید،معادل همین peer خواهد بود.در حالت سوم سیستم علاوه بر نام کاربری معرفی شده در Postgresql، نیاز به کلمه عبور دارد.یکی از مهمترین برچسب های این دسته md5 است.یعنی در هنگام ارسال اطلاعات اتصال،کلمه عبور به صورت md5 ارسال شود.دقت کنید که اگر در هنگام برنامه نویسی در حالت ایجاد Connection String هستند،شما باید کلمه عبور را به صورت دقیق وارد کنید و این درایو اتصال است که آن را به صورت md5 برای پایگاه داده در شبکه ارسال می‌کند.برای ملاحظه‌ی اطلاعات بیشتر می توانید به صفحه رسمی Postgresql در این آدرس مراجعه کنید.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Sat, 30 May 2020 18:53:26 +0430</pubDate>
            </item>
                    <item>
                <title>نکاتی در مورد نصب آرچ</title>
                <link>https://virgool.io/@SMAH1/%D9%86%DA%A9%D8%A7%D8%AA%DB%8C-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-%D9%86%D8%B5%D8%A8-%D8%A2%D8%B1%DA%86-b651oay6c7yj</link>
                <description>با توجه به اینکه بسیار کنجکاو بودم که یک توزیع دیگه لینوکسی (به غیر از ابونتو) رو به صورت طولانی مدت تجربه کنم،آرچ رو انتخاب کردم.چند روز پیش برای بار دوم اون رو نصب کردم (در کنار ابونتو و ویندوز).در فرآیند نصب آرچ به مشکلات و نکاتی برخوردم که به نظرم شاید برای شما هم مفید باشه.نصب آرچ توسط یک توزیع لینوکسی دیگراگر شما هم اکنون در حال استفاده از یک توزیع لینوکسی دیگر هستید،برای نصب آرچ حتما نیاز به Live CD نیست.راه حل در اینجا توضیح داده شده است.بطور خلاصه،کافیست فایل archlinux-bootstrap رو دانلود کنید و بعد توسط tar بازش کنید و در نهایت arch-chroot کنید و سپس ادامه مراحل نصب رو مانند یک «دیسک زنده» پیگیری کنید.برای نصب حتما نیاز به یک Live CD بروز نیستهر چند عمدتا توصیه می‌شود که بهتر است همیشه آخرین نسخه Live CD آرچ رو تهیه کنید و بعد به نصب بپردازید ولی عملا می توانید از یک نسخه قدیمی آرچ هم برای نصب استفاده کنید.البته به یاد داشته باشید که در اینصورت پس از اتصال به اینترنت (در مراحل نصب آرچ) به عنوان اولین کار،دستور زیر را وارد کنید:pacman -S archlinux-keyringاین دستور باعث می‌شود که keyring ها بروز شود و همواره آخرین نسخه‌ی بسته‌ها نصب گردد.برای بروز کردن آرچ می‌توانید از ابونتو کمک بگیریدیکم عجیب است ولی کاملا ممکن است.من کمتر به آرچ سر می‌زنم ولی تمایل دارم که همواره آرچ بروزی داشته باشیم.به همین دلیل در ابونتو اقدام به بروزرسانی آرچ خودم میکنم.برای این منظور در ابتدا بسته‌ی arch-install-scripts رو توی ابونتو نصب کنید.یعنی:sudo apt install arch-install-scriptsحالا با فرض اینکه آرچ بر روی پارتیشن sda5 قرار دارد، داریم:sudo mount /dev/sda5 /mnt
sudo arch-chroot /mnt /bin/bashکه در دستور اول پارتیشن آرچ را mount می‌کنید و در دستور دوم به آن arch-chroot می‌کنید.حالا دقیقا مثل زمانی است که در آرچ قرار دارید.کافیست تایپ کنید:pacman -Syuصاحب پارتیشن آرچ کیست؟همواره در فرآیندهای نصب تاکید می‌شود که در اولین مراحل نصب (بعد از بالا آمدن Live CD) اقدام به format کردن پارتیشن آرچ کنید و سپس به نصب آن بپردازید.شاید فکر کنید که این نکته برای خالی کردن پارتیشن از هرگونه فایل اضافه‌است وی دلیل آن فراتر از این است.من در ابونتو توسط ابزار Disk گنوم اقدام به فرمت پارتیشن مورد نظر کردم و سپس فرآیند نصب را انجام دادم.همه چیز به خوبی پیش رفت تا اینکه gdm را نصب کردم.به از reboot با اینکه سرویس gdm فعال بود ولی عملا وارد حالت گرافیکی نشدم و صفحه فریز شد.بعد از بررسی بیشتر متوجه شد که در هنگامی که با کاربر root وارد سیستم می‌شوم با دستور startx می‌توانم به Desktop دسترسی داشته باشم ولی هنگامی که می‌خواستم با کاربری غیر از root وارد سیستم شود،به سرعت logout می‌کرد.بعد از کلی بررسی متوجه شد که پوشه‌ی «/» یا همان «روت فایل سیستم» دارای group دیگری است به اسم «unknow» در واقع چون گروه موجود نبود این نام را به جایش نمایش می‌داد.در نتیجه بهتر است یکی از دو کار زیر را قبل از شروع فرایند نصب (پس از بالا آمدن Live CD و قبل از انجام هر کاری) انجام دهید:اول: پارتیشن آرچ را فرمت کنیددوم: و یا دستور زیر را بزنید و صاحب پارتیشن را بررسی کنید:stat /و اگر root به عنوان کاربر و گروه ثبت نشده است حتما قبل از آن با استفاده از chown و یا chgrp اقدام به تغییر صاحب آن به root کنید.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Tue, 12 May 2020 16:20:56 +0430</pubDate>
            </item>
                    <item>
                <title>غیر فعال کردن hypervisor در ویندوز 10</title>
                <link>https://virgool.io/@SMAH1/%D8%BA%DB%8C%D8%B1-%D9%81%D8%B9%D8%A7%D9%84-%DA%A9%D8%B1%D8%AF%D9%86-hypervisor-%D8%AF%D8%B1-%D9%88%DB%8C%D9%86%D8%AF%D9%88%D8%B2-10-s4jiz2bpjh06</link>
                <description>می‌خواستم چند apk از منبع ناشناس رو بررسی کنم.به ذهنم رسید که روی یک ماشین مجازی امتحان کنم.بعد از بررسی تصمیم گرفتم BlueStacks نصب کنم.و ماجرا از اینجا شروع شد.چند روز درگیری و البته چند بار تعویض ویندوز (دقیق‌تر: Restore پارتیشن ویندوز).من windows 10 version 1909 دارم.و البته برای کنجکاری Hyper-V رو روی اون فعال کردم (هر چند هیچ وقت استفاده نکردم).هنگام نصب BlueStacks با خطایی مواجه شدم و بعد از جستجو متوجه شدم باید HAXM رو نصب کنم.اما نصب HAXM با خطای زیر همراه بود.This computer does not support Intel Virtualization Technology (VT-x) or it is being exclusively used by Hyper-V. HAXM cannot be installed.
Please ensure Hyper-V is disabled in Windows Features, or refer to the Intel HAXM documentation for more informationخطا هنگام نصب HAXMکه صریحا می‌خواست که Hyper-V رو غیر فعال کنم.بعد از جستجو و اجرای دستور عمل‌ها هم باز مشکل پابرجا بود.خلاصه‌ی دستور عمل‌ها رو می‌تونید از اینجا مطالعه کنید.که عبارت بودند از:۱. فعال سازی عناوینی شبیه VT-x, VT-d, Virtualization Technology توی BIOS۲. حذف Hyper-V۳. غیر فعال کردن Core Isolation۴. دستور «bcdedit /set hypervisorlaunchtype off»و البته هنوز مشکل وجود داشت.جالبه که با غیر فعال کردن Hyper-V و عدم نصب HAXM برنامه‌ی VirtualBox هم دیگه اجرا نمی‌شد.برای دیدن مشکل کافی بود دستور systeminfo رو توی cmd بزنید تا در خط آخر عبارت زیر رو ببینید:Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.بعد از بررسی فهمیدیم که چیزی به نام hypervisor وجود داره که در واقع یک لایه بالاتر از امثال Hyper-V و HAXM یا هر ماشین مجازیی است و کنترل کننده اصلی مجازی سازی است.در واقع یک مدیر برای مجازی سازی است.و برای غیر فعال کردنش همان دستور توی مرحله 4 در توضیحات بالا کافیست.البته اگر از UEFI استفاده نمی‌کنید! و چون من از بوت امن UEFI استفاده می کردم چند روز وقتم گرفته شد تا در اینجا راه حل رو پیدا کردم.برای این راه حل ابتدا یک Drive Letter خالی ویندوز رو انتخاب کنید (در این مثال L) و بعد دستورات زیر رو بزنید:D:\&gt; set FREE_MOUNT_VOL_DRIVELETTER=L:
D:\&gt; mountvol %FREE_MOUNT_VOL_DRIVELETTER% /s
D:\&gt; copy C:\WINDOWS\System32\SecConfig.efi %FREE_MOUNT_VOL_DRIVELETTER%\EFI\Microsoft\Boot\SecConfig.efi /Y
D:\&gt; bcdedit /create {0cb3b571-2f2e-4343-a879-d86a476d7215} /d &amp;quotDG&amp;quot /application osloader
D:\&gt; bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} path &amp;quot\EFI\Microsoft\Boot\SecConfig.efi&amp;quot
D:\&gt; bcdedit /set {bootmgr} bootsequence {0cb3b571-2f2e-4343-a879-d86a476d7215}
D:\&gt; bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions DISABLE-LSA-ISO,DISABLE-VBS
D:\&gt; bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} device partition=%FREE_MOUNT_VOL_DRIVELETTER%
D:\&gt; mountvol %FREE_MOUNT_VOL_DRIVELETTER% /d
D:\&gt; shutdown /t 0 /rکه البته دستور آخر مربوط به Restart ویندوز میشه.بعد از بوت با پیغامی روبروی میشید که می خواهد Credentials Guard and virtualization based security رو غیر فعال کنه.Credentials Guardغیرفعال کردن با زدن F3 آن را غیر فعال کنید.و بعد از بالا آمدن ویندوز به راحتی HAXM رو نصب کنید.</description>
                <category>SMAH1</category>
                <author>SMAH1</author>
                <pubDate>Mon, 11 May 2020 19:01:37 +0430</pubDate>
            </item>
            </channel>
</rss>