<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF 
					 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
					 xmlns="http://purl.org/rss/1.0/"
					 xmlns:dc="http://purl.org/dc/elements/1.1/"
					>
<channel rdf:about="/blog/rss10"><title>Technical Learning</title>
<link>/blog/rss10</link>
<description><![CDATA[Daily blog of technology learned during the day.<br>]]></description>
<items>
<rdf:Seq>
<rdf:li resource="/blog/view/2"/>
<rdf:li resource="/blog/view/3"/>
<rdf:li resource="/blog/view/4"/>
<rdf:li resource="/blog/view/5"/>
<rdf:li resource="/blog/view/6"/>
<rdf:li resource="/blog/view/7"/>
<rdf:li resource="/blog/view/8"/>
<rdf:li resource="/blog/view/9"/>
<rdf:li resource="/blog/view/10"/>
<rdf:li resource="/blog/view/11"/>
<rdf:li resource="/blog/view/12"/>
<rdf:li resource="/blog/view/13"/>
<rdf:li resource="/blog/view/14"/>
<rdf:li resource="/blog/view/15"/>
<rdf:li resource="/blog/view/16"/>
<rdf:li resource="/blog/view/17"/>
<rdf:li resource="/blog/view/18"/>
</rdf:Seq>
</items>
</channel>
<item rdf:about="/blog/view/2">
<title>Docker</title>
<link>/blog/view/2</link>
<dc:date>2023-12-17</dc:date>
<description><![CDATA[<p>The term docker is often thrown around.   It turns out to be fairly complex as a it crosses</p><p>across the developer, qa, release, and system admin roles.</p><p>Its supposed to make all these easier and more consistent.</p><p><br></p><p>So</p><p>1. Docker is a unix/linux/macos command line utility</p><p>    It provides utilies to push, pull images, start up the image, stop the image , remove the image.  <br></p><p><br></p><p>2. Dockerfile is a file that specifies how to create an image for distribution.</p><p>    This is used at the point of release. </p><p><br></p><p>3. docker-compose is a command line utility that processes the file docker-compose.y[a]ml</p><p>    docker-compose.yml defines a development environment that  developer can use</p><p>    to edit/add/manage code. <br></p><p><br></p>]]></description>
</item>
<item rdf:about="/blog/view/3">
<title>StarLink</title>
<link>/blog/view/3</link>
<dc:date>2024-01-10</dc:date>
<description><![CDATA[<p>I recently upgraded to StarLink.   I purchased the hardware through Amazon.</p><p>It took 2-3 weeks from when I ordered it before I received the hardware.</p><p>StarLink is an internet service run via satellites.     <br></p><p>It has matured in the last several years to the point where it is usable for a developer.</p><p>Before ordering you should check to see if its available in your area.</p><p>Go to http://starlink.com <br></p><p><br></p><p>Some technical notes:</p><p>1) I have android, and you want to set up your account on the starlink website first.</p><p>    The android setup of accounts is slightly broken... essentially when you begin</p><p>   to identify locations, the android app ends up with a blank screen.</p><p>   If you have an existing account, you can skip the blank screen issue.</p><p><br></p><p>2) Once you have activated your dish, http://dishy.starlink.com is actually</p><p>    the router on your local net.  Its useful because you can test the speed</p><p>    of the dish from the router.   In my case 83 Mbs down, 14 mbs up.</p><p><br></p>]]></description>
</item>
<item rdf:about="/blog/view/4">
<title>Upgrading Servers</title>
<link>/blog/view/4</link>
<dc:date>2024-03-01</dc:date>
<description><![CDATA[Jan 11, 2024<br>============<br>- need to have knowledge<br>   a) laravel<br>   b) symphony<br>   c) codeigniter<br>   d) nosql<br>   e) reactjs<br>- these are good blog topics<br>- more topics<br>    a) postgresql<br>    b) mongodb<br>    c) git<br><br>5:30pm - look at codeigniter<br><br>       Php Configuration:<br>        https://www.codeigniter.com/user_guide/intro/requirements.html<br>    <br>        codeigniter requires a number of php extensions<br>     a) intl   = php configure --enable-intl <br>     b) mbstring = php configure --enable-mbstring<br>     c) json   = included by default<br>     d) mysqlnd = php configure --with-msqli=mysqlnd<br>     e) curl  = php configure --with-curl<br>     f) imagick = pecl install imagick<br>     g) gd = php configure --with-gd<br>           = php8 configure --enable-gd<br>     h) simplexml = enabled by default<br>     i) memcache = installed via pecl<br>     j) memcached = installed via pecl<br>     k) redis = installed via pecl<br>     l) dom   = enabled by default<br>     m) libxml = enabled by default<br>     n) xdebug = pecl install xdebug<br>     <br>    <br>5:33pm - need to upgrade dev2 to php 8<br>       I build php from source<br>       Latest php version is 8.3.1<br>       downloadable from http://php.net<br>       <br>       pecl has a problem due to cacert.pem<br>       configure php.ini<br>       openssl.cafile=/usr/local/ssl/cacert.pem<br>       cd /usr/local/ssl<br>       wget http://curl.haxx.se/ca/cacert.pem<br>       This will download the cacert.pem with the update ca certs<br>       To see the cacert locations:<br>       php -r "print_r(openssl_get_cert_locations());"<br><br>6:30pm - apache is out of data.   Latest version is apache-2.4.58<br><br>7:11pm - so upgrade of php impacts the pearpkgs included<br>       by the software.<br>       Had to modify pearpkgs/Pear.pm<br>       Found bug in pearpkgs/MDB2/Mysqli.php<br>       <br><br>10:18pm - so it turns out that you can configure the php.ini to format<br>       the error outputs so its a little nicer in php.ini<br>       <br>       html_errors=On<br>       error_prepend_string="<pre style='border:solid 1px #CC000'>"<br>       error_append_string = "</pre>";<br><br>12:32am - so since I upgraded mariadb when I switched servers<br>       the database will not accept a blank string into an integer.<br>       This turns out to be a configuration set mariadb<br>       (mariadb is a version of mysql)<br>       select @@sql_mode<br>       edit /etc/my.cnf.d/mariadb-server.cnf<br>       add<br>       sql_mode=""<br><br>2:41am - recompiling php to include zlib<br>      ./configure --with-zlib<br><br>3:56am - added browscap ini item in php.ini<br>      browscap=/usr/local/lib/php/php_browscap.ini<br>      <br>4:09am - build apache 2.4.58 and of course rebuild php-8.3.1<br><br><br>       <br>Jan 12, 2024<br>============<br>2:00pm - going to upgrade groupcorners to apache-2.4.58,php-8.3.1<br><br>2:42pm - php upgrade fails because its missing oniguruma-devel package.<br>       which apparently does not exist on redhat os 8.2<br><br>       to get it:<br>       https://github.com/kkos/oniguruma<br>       download zip, and unzip it.  Probably ignore the INSTALL<br>       read file.<br><br>       to build it:<br>       yum install automake<br>       yum install autoconf<br>       autoreconf -fi<br>       ./configure<br>       make<br>       make install<br><br>       then  modify your build script for php-8.3.1<br>       add before configure<br>       export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig<br><br>6:41pm - got php-8.3.1 to compile without mbstring<br>       had to add CFLAGS=-fPIC to configure statement<br>       and remove -enable-mbstring<br>       need to enable zip and imagick -*-*+90<br><br>Jan 13, 2024<br>============<br>4:33 pm  added zip to php<br>       pecl install zip<br><br>4:53pm   install imagick on groupcorners.com<br>       so the standard install<br>       pecl install imagick - fails in php 8.3.0<br>       So get the source from http://github.com/imagick<br>       unzip imagick-master<br>       cd imagick-master<br>       phpize<br>       ./configure<br>       make<br>       make install<br>       copy imagick.so from no-debug* under /usr/local/lib/php/extensions<br>       to /usr/local/lib/php/extensions<br>       <br>10:06pm - so mbstring fails to compile in php.<br>        a) the LDFLAGS in configure is not honored, so you<br>       need to add any thing in CFLAGS<br>    b) gcc is used to compile php, gcc uses binutils to<br>       link the objecs. Apparently the binutils on<br>       redhat 8.9, which groupcorners is running is not<br>       high enough version.  Apparently I need a version<br>       higher that 2.32 (groupcorners is running 2.30)<br><br>       So.. the answer is recompile binutils, and recompile<br>       gcc - and use the new gcc to compile php.<br><br>11:54pm   rebuilt php-8.3.1 with new gcc successfully.<br>        mbstring now compiles.<br><br>]]></description>
</item>
<item rdf:about="/blog/view/5">
<title>TypeScript</title>
<link>/blog/view/5</link>
<dc:date>2024-02-09</dc:date>
<description><![CDATA[These are basic takeaways from reading about typescript<br>So typescript is compiled javascript with strict typing. <br><the primary="" advantage="" that="" you="" get="" from="" typescript="" is="" data="" type="" checkingthrough="" compilation.   ="" javascript="" by="" itself="" does="" not="" have="" any="" checking<br><br>1) Install typescript<br>npm i -g typescript<br>2) Check version<br>tsc -v <br>3) Compile stuff in .ts files to .js files<br>tsc -w<br><br>4) Defining variables<br>     let varname: type = default_value;<br>   types can be string, number, bigint, bool, null, undefined, symbol<br>   wrappers String,Number,BigInt, Boolean, Symbol<br>   union type: example : let foo: string|number=5;<br><br>   "any" type - not recommended - reverts to straight javascript<br>   const foo = document.querySelector('a')!;<br>   ! - indicates - non-null assertion to inform compiler<br>   type casting:<br>   const foo = document.getElementById('foobar') as HTMLFormElement;<br>   let flavors: 'chocolate'|'strawberry'|'blueberry';<br>   <br>5) reference types - arrays, objects, functions<br>  a) arrays<br>      let myarray: number[] = [1,2,4,5];<br>      let myarray: (number|boolean)[] = [1,true,2];<br>  b) tuples<br>      let mytuple: [string,number,boolean] = ['Danny,1,true];<br>  c) objects<br>     let person: {<br>          name: string;<br>     alive: boolean;<br>     };<br>     person = { name:"Tom"; alive:true};<br>     person.name = "Mike";<br>  3) interfaces<br>     interface Person<br>     {<br>        name: string;<br>    alive:true;<br>    sayHi(name:string):string;<br>    sayBye(name:string) => string;<br>     }<br><br>     let something:Person {<br>        sayHi: function (name:string)<br>    {<br>        return 'Hi ${name}';<br>    }<br>     }<br>     usage:<br>       let person1:Person { name:"mike",alive:true};<br>  d) functions<br>     <br>     function funcname(arg1:type,arg2?:type):return_type<br>     {<br>     }<br>     or with es6<br>          const funcname = (arg1:type,arg2?:type):return_type =><br>      {<br>      }<br>     ? means optional argument.    <br>     signature:<br>     let funcname: (arg1:type):null;<br>  e) types<br>      type PersonObject= {<br>         name:string;<br>     age: number;<br>      }<br><br>  f) classes<br>  <br>        class classname {<br>       private name: string;<br>        protected age: number;<br>        constructor(n:string,a:number) {<br>          this.name = n;<br>          this.age = a;<br>          }<br>        display() {<br>            return "Name: ${this.name} age:${this.age}";<br>        }<br><br>     let people: Person[] = [person1,person2];<br><br>    definition of scope of variables:<br>     readonly name: string; // This property is immutable - it can only be read<br>     private isCool: boolean; // Can only access or modify from methods within this class<br>     protected email: string; // Can access or modify from this class and subclasses<br>      public pets: number; // Can access or modify from anywhere - including outside the class<br><br>   g) generics<br>      const addID = <t extends="" {="" name:="" string="" }="">(obj: T) => {<br>      let id = Math.floor(Math.random() * 1000);<br><br>      return { ...obj, id };<br>     };<br>   <br>     interface hasLength {<br>      length: number;<br>     }    <br><br>     function logLength<t extends="" haslength="">(a: T) {<br>        console.log(a.length);<br>       return a;<br>     }<br><br>  h) enums<br>      enum states { AL="AL",<br></t></t></the><p><the primary="" advantage="" that="" you="" get="" from="" typescript="" is="" data="" type="" checkingthrough="" compilation.   ="" javascript="" by="" itself="" does="" not="" have="" any="" checking<br=""><t extends="" {="" name:="" string="" }=""><t extends="" haslength="">                   AK="AK"};</t></t></the></p><p><the primary="" advantage="" that="" you="" get="" from="" typescript="" is="" data="" type="" checkingthrough="" compilation.   ="" javascript="" by="" itself="" does="" not="" have="" any="" checking<br=""><t extends="" {="" name:="" string="" }=""><t extends="" haslength=""><br> </t></t></the></p><p><the primary="" advantage="" that="" you="" get="" from="" typescript="" is="" data="" type="" checkingthrough="" compilation.   ="" javascript="" by="" itself="" does="" not="" have="" any="" checking<br=""><t extends="" {="" name:="" string="" }=""><t extends="" haslength="">6. typescript interacts with multiple react platforms:</t></t></the></p><the primary="" advantage="" that="" you="" get="" from="" typescript="" is="" data="" type="" checkingthrough="" compilation.   ="" javascript="" by="" itself="" does="" not="" have="" any="" checking<br=""><li>    create-react-app (TS setup)</li><li>    Gatsby (TS setup) Next.js</li><li>    Next.js (<a href="https://nextjs.org/learn/excel/typescript">TS setup</a>)</li><p>Concise tutorial:</p><p><br></p><p>https://www.freecodecamp.org/news/learn-typescript-beginners-guide/</p></the>]]></description>
</item>
<item rdf:about="/blog/view/6">
<title>mongodb</title>
<link>/blog/view/6</link>
<dc:date>2024-02-22</dc:date>
<description><![CDATA[MongoDB<br><br>https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-amazon/<br><br>To install:<br>a) set up yum repo<br>&nbsp; /etc/yum.repos.d/mongodb-org-7.0.repo file should contain<br>#############################################<br>[mongodb-org-7.0]<br>name=MongoDB Repository<br>baseurl=https://repo.mongodb.org/yum/amazon/2023/mongodb-org/7.0/x86_64/<br>gpgcheck=1<br>enabled=1<br>gpgkey=https://pgp.mongodb.com/server-7.0.asc<br>##############################################<br><br>b) mongodb runs a user mongod, systemctl start mongod<br>&nbsp;&nbsp; /var/lib/mongo is repository<br>&nbsp;&nbsp; /var/log/mongodb is logging directory<br>&nbsp; &nbsp;<br>c) mongosh = mongo shell <br>&nbsp;&nbsp; test&gt; use mydb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // change to database<br>&nbsp;&nbsp; mydb&gt; show collections&nbsp; // show collections<br><br>&nbsp;&nbsp; db.users.insertOne(['username'=&gt;'triemer']);<br>&nbsp;&nbsp; db.users.find();<br><br><br><br>d) So install on amazon 2023 doesn't work for mongosh<br>&nbsp;&nbsp; &gt; dnf remove mongodb-mongosh<br>&nbsp;&nbsp; &gt; dnf install -qy mongodb-mongosh-shared-openssl3<br><br>e) For PHP, install mongodb extension<br>&nbsp;&nbsp; -- Install the mongodb extension to php<br>&nbsp;&nbsp; &gt;pecl install mongodb<br>&nbsp;&nbsp; (I chose all the defaults)<br>&nbsp;&nbsp; &gt; cd /usr/local/lib/php/extensions<br>&nbsp;&nbsp; mongodb built in subdir... copy up one level<br>&nbsp;&nbsp; &gt;add extension=mongodb.so to php.ini (/usr/local/lib/php.ini)<br><br>&nbsp;&nbsp; -- now install php library<br>&nbsp;&nbsp; in your php project where composer.json is<br>&nbsp;&nbsp; composer require mongodb/mongodb<br>&nbsp; &nbsp;<br><br>f) basic code to initiate mongodb from php<br>&nbsp; From: https://www.mongodb.com/docs/php-library/current/tutorial/crud/<br>&nbsp; <br>&nbsp; &lt;?php<br>&nbsp;&nbsp;&nbsp;&nbsp; require_once "lib/vendor/autoload.php";<br>&nbsp;&nbsp;&nbsp;&nbsp; $serverApi = new ServerApi(ServerApi::V1);<br>&nbsp;&nbsp;&nbsp;&nbsp; $client = new MongoDB\Client('mongodb://127.0.0.1',[],['serverApi'=&gt;$serverApi]);<br><br><br>&nbsp; CRUD operations:<br>&nbsp; define the collection:<br>&nbsp; $collection = $client-&gt;test-&gt;users&nbsp; ( creates a users table in test database)<br>&nbsp; // CREATE<br>&nbsp; $result =$client-&gt;insertOne(['username'=&gt;'admin',email=&gt;admin@fubar.com']);<br>&nbsp; Get Count: echo $result-&gt;getInsertedCount();<br>&nbsp; Get Inserted Id: echo $result-&gt;getInsertedId();<br>&nbsp; <br>&nbsp; $result = $client-&gt;insertMany(<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; ['username'=&gt;'admin','email'=&gt;'admin@fubar.com'],<br>&nbsp;&nbsp; &nbsp;&nbsp; ['username'=&gt;'tom','email'=&gt;'tom@fubar.com']<br>&nbsp;&nbsp; &nbsp;&nbsp; );<br>&nbsp; Get Count: echo $result-&gt;getInsertedCount();<br>&nbsp; Get Inserted Ids: echo $result-&gt;getInsertedIds();<br><br>&nbsp; // SERACH<br>&nbsp; $cursor = $collection-&gt;find(['username'=&gt;'admin',<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; 'last_name'=&gt; MongoDB\BSON\Regex('^garden', 'i')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ],$options);<br>&nbsp; // Mix and match options<br>&nbsp;&nbsp;&nbsp;&nbsp; $options = ['projection'=&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ['username'=&gt;1,<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'first_name'=&gt;1,<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'last_name'=&gt;1],<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 'limit'=&gt;4,<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 'sort'=&gt;['pop' =&gt; -1],<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 'sort'=&gt;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; ];<br><br><br>&nbsp;&nbsp; Update<br>&nbsp;&nbsp; ------<br>&nbsp;&nbsp; $result = $collection-&gt;updateOne(<br>&nbsp;&nbsp; &nbsp;['name'=&gt;'Tom']<br>&nbsp;&nbsp; &nbsp;['$set'=&gt;['address'=&gt;'123 test way']]<br>&nbsp;&nbsp; &nbsp;);<br>&nbsp;&nbsp;&nbsp; $count = $result-&gt;getMatchedCount();<br>&nbsp;&nbsp;&nbsp; $modified = $result-&gt;getModifiedCount();<br><br>&nbsp;&nbsp; $result = $colletion-&gt;updateMany(<br>&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ['state'=&gt;'ny'],<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ['$set'=&gt;['country'=&gt;'us']));<br>&nbsp;&nbsp; ** Updated only updates the fields mentioned **<br><br>&nbsp;&nbsp; Replace<br>&nbsp;&nbsp; -------<br>&nbsp;&nbsp; $result = $collection-&gt;replaceOne(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ['name'=&gt;'Tom'],&nbsp;&nbsp;&nbsp; // filter<br>&nbsp;&nbsp; &nbsp;['username'=&gt;'thomas',&nbsp; // new document<br>&nbsp;&nbsp; &nbsp; 'last_name'=&gt;'myname']);<br>&nbsp;&nbsp;&nbsp; $count = $result-&gt;getMatchedCount();<br>&nbsp;&nbsp;&nbsp; $modified = $result-&gt;getModifiedCount();<br><br>&nbsp; /* This replaces all fields */<br><br>&nbsp; Upsert<br>&nbsp; ------<br>&nbsp; <br>&nbsp;&nbsp;&nbsp; $updateResult = $collection-&gt;updateOne(<br>&nbsp;&nbsp;&nbsp; ['name' =&gt; 'Bob'],<br>&nbsp;&nbsp;&nbsp; ['$set' =&gt; ['state' =&gt; 'ny']],<br>&nbsp;&nbsp;&nbsp; ['upsert' =&gt; true]<br>);<br>&nbsp;&nbsp;&nbsp; ** updates the table if exists, creates if not */<br>&nbsp;&nbsp; &nbsp;<br>&nbsp; Delete<br>&nbsp; ------<br>&nbsp; $collection-&gt;deleteOne(['name'=&gt;'bob']);<br>&nbsp; $collection-&gt;deleteMany(['name'=&gt;'tom']);<br>&nbsp; <br><br>&nbsp; Indexes<br>&nbsp; $collection-&gt;createIndex(['name'=&gt;1]);<br>&nbsp; foreach ($collection-&gt;listIndexes() as $indexInfo) {<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; var_dump($indexInfo);<br>&nbsp; }<br>&nbsp; $collection-&gt;dropIndex();<br>&nbsp; $collection-&gt;dropIndexes(); // drops all indexes on collection<br>&nbsp; <br>------------------------<br>installation on rhel 8.9<br>-------------------------<br>https://linuxconfig.org/how-to-install-mongodb-on-redhat-8<br><br>Then follow commands above to install pecl and library<br><br>-------------------------<br>Enable authentiction<br>-------------------------<br>1. create an admin user<br>&nbsp;&nbsp; use admin<br>&nbsp;&nbsp; createUser( { user:"myUserAdmin", pwd:"mypath",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br><br>2. configure /etc/mongod.conf<br>&nbsp;&nbsp; Security:<br>&nbsp;&nbsp;&nbsp;&nbsp; authorization:enabled<br><br>3. now create user in the database<br>&nbsp;&nbsp; user admin<br>&nbsp;&nbsp; db.auth("myUserAdmin","mypath")<br>&nbsp; &nbsp;<br>&nbsp;&nbsp; use mydb<br>&nbsp;&nbsp; createUser( { user:"fancyuser", pwd:"mypass",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles: [ { role: "readWrite", db:"mydb"}]<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; })<br>&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>4. in php configure the url for the collection connection<br>&nbsp;&nbsp; $collection = new MongoDB\Client('mongodb://fancyuser:mypass@127.0.0.1/mydb');<br>&nbsp;&nbsp; e.g. mongodb://user:password@127.0.0.1/database<br>&nbsp; &nbsp;<br>----------------------------------<br>Creating a database<br>----------------------------------<br>Bit weird here...<br>1. authorize with myUserAdmin<br>&nbsp; &gt; use admin<br>&nbsp; &gt; db.auth("myUserAdmin","mypath")<br>&nbsp; &gt; use newdb<br>&nbsp; &gt;&nbsp;&nbsp;&nbsp; createUser( { user:"fancyuser", pwd:"mypass",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles: [ { role: "readWrite", db:"newdb"}]<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; })<br><br>2. the database will not show up in user databases<br>&nbsp;&nbsp; until something is written to it.<br><br>3. BUT the authorization works.<br><br>]]></description>
</item>
<item rdf:about="/blog/view/7">
<title>Python</title>
<link>/blog/view/7</link>
<dc:date>2024-02-22</dc:date>
<description><![CDATA[https://developers.google.com/edu/python<br><br>1. build python<br>&nbsp;&nbsp; ./configure<br>&nbsp;&nbsp; make<br>&nbsp;&nbsp; make install<br><br>2. install gunicorn<br>&nbsp;&nbsp; pip3 install gunicorn<br><br>3. in apache enable proxy modules<br>LoadModule proxy_module modules/mod_proxy.so<br>LoadModule proxy_http_module modules/mod_proxy_http.so<br><br>4. add ProxyPass entry in vhost<br>ProxyPass "/pybase/" "http://127.0.0.1:8000/"<br><br>5. configure gunicorn.service file in&nbsp; /usr/lib/systemd/system/gunicorn.service<br><br>===== Start gunicorn.service File ======<br>[Unit]<br>Description=The Apache HTTP Server<br>After=network.target<br><br>[Service]<br>MAINPID = /run/cmdb/cmdb.pid<br>WorkingDirectory = /m/member/pybase<br>ExecStartPre = /bin/mkdir /run/cmdb<br>ExecStart=/usr/local/bin/gunicorn --workers=4 myapp:app --chdir="/m/member/pybase" --pid /run/cmdb/cmdb.pid<br>ExecReload=/bin/kill -s HUP $MAINPID<br>ExecStop=/bin/kill -s HUP $MAINPID<br>ExecStopPost = /bin/rm -rf /run/cmdb<br><br>PrivateTmp=true<br><br>[Install]<br>WantedBy=multi-user.target<br><br>===== End gunicorn.service File ======<br><br>A) definition of a function<br>&nbsp; def funcname(arg1,arg2):<br><br>B) spacing matters - indentation defines block<br><br>C) definition of if statement<br>&nbsp; if (a == 1):<br>&nbsp;&nbsp;&nbsp;&nbsp; a += 1;<br><br>D) for statement<br>&nbsp;&nbsp; for (x in environ):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data += x+environ[x];<br><br>E) Templates<br>&nbsp;&nbsp; Jinja2 is the most prevalent template engine<br>&nbsp;&nbsp; sample code to load from file:<br><br>&nbsp;&nbsp; import jinja2<br>&nbsp;&nbsp; def display_template():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; templateLoader = jinja2.FileSystemLoader(searchpath="./templates")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; templateEnv = jinja2.Environment(loader=templateLoader)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; templateFile = "template.html"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template = templateEnv.get_template(templateFile)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return template.render();<br><br>F) getting data from the database<br>&nbsp;&nbsp; - basic level method (cursor)<br>&nbsp;&nbsp; ---------------------------------<br>&nbsp;&nbsp; import mysql.connector<br>&nbsp;&nbsp; def get_data(sql):<br>&nbsp;&nbsp;&nbsp;&nbsp; cnx = mysql.connector.connect(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user='membermaster',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; password='XXXXX',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host='127.0.0.1',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; database='mainmemberdb')<br><br>&nbsp;&nbsp;&nbsp; data = "&lt;table&gt;\n"<br>&nbsp;&nbsp;&nbsp; if cnx and cnx.is_connected():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; with cnx.cursor() as cursor:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = cursor.execute(sql)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rows = cursor.fetchall()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for row in rows:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data += "&lt;tr&gt;\n"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for col in row:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data += "&nbsp;&nbsp; &lt;td&gt;"+col+"&lt;/td&gt;\n"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data += "&lt;/tr&gt;\n"<br>&nbsp;&nbsp;&nbsp; data += "&lt;/table&gt;\n\n"<br>&nbsp;&nbsp;&nbsp; cnx.close()<br>&nbsp;&nbsp;&nbsp; return data<br>&nbsp;&nbsp; ---- end code --------<br>&nbsp;&nbsp; -More sophisticated is to use pandas to load the data to a grid<br>&nbsp;&nbsp; pandas can output the data in a number of formats<br>&nbsp;&nbsp; pandas is a library that allows data to be loaded into a grid<br>&nbsp;&nbsp; that can then be displayed. <br>--------------------------------------------------------------<br>def get_table(sql):<br>&nbsp;&nbsp; try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cnx = mysql.connector.connect(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user='membermaster',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; password='XXXXX',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host='127.0.0.1',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; database='mainmemberdb')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; results = pd.read_sql(sql,cnx)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cnx.close()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # html table has systables as a css class systables in addition to<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # dataframe... e.g. &lt;table class='dataframes systables'&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return results.to_html( classes= "systables")<br>&nbsp;&nbsp; except Exception as e:<br>&nbsp;&nbsp;&nbsp; cnx.close()<br>&nbsp;&nbsp;&nbsp; return str(e)<br>---- end code -----<br><br>G) Get an argument from command line<br>&nbsp;&nbsp; import sys<br>&nbsp;&nbsp; def main():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (len(sys.argv)&gt;=2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("ARG 1:",sys.argv[1]);<br><br>&nbsp;&nbsp;&nbsp; if __name__ == '__main__':<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; main()<br><br>H) repeat string... * syntax<br>&nbsp;&nbsp; print("foo"*3);<br>&nbsp;&nbsp; &gt;&gt;foofoofoo<br><br>I) From the command line - help(keyword)<br>&nbsp;&nbsp; help(len)<br><br>J)To convert numbers to strings<br>&nbsp;&nbsp;&nbsp; mystring = str(10);<br><br>K) numbers:<br>&nbsp;&nbsp; 1. no ++ - can't do a++<br>&nbsp;&nbsp; 2. integer division is two // e.g. 2.4 // 2 = 1<br><br>L) raw strings<br>&nbsp;&nbsp; raw= r'this\t\n and that'<br>&nbsp;&nbsp; multi= """ hello<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; world """<br><br>M) slices<br>&nbsp;&nbsp; s="hello";<br>&nbsp;&nbsp; something = s[1:4]<br>&nbsp;&nbsp; &gt;&gt;&gt; 'ell'<br>&nbsp;&nbsp; s[-1]<br>&nbsp;&nbsp; &gt;&gt; 'o'<br>N) strings<br>&nbsp;&nbsp; [f strings]<br>&nbsp;&nbsp;&nbsp; value = 2.791514<br>&nbsp;&nbsp;&nbsp; print(f'approximate value = {value:.2f}') <br><br>O) if statements<br>&nbsp;&nbsp;&nbsp; if a==b:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("a equals b")<br>&nbsp;&nbsp;&nbsp; elif c==d<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("c equals d")<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("magic")<br><br>P) and/or&nbsp; ( there is no &amp;&amp; or || )<br>&nbsp;&nbsp; if a and b:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(true)<br>&nbsp;&nbsp; if a or b<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print(false)<br><br>Q) for/in<br>&nbsp;&nbsp; for key in list:<br>&nbsp;&nbsp;&nbsp;&nbsp; iterate here<br>&nbsp;&nbsp; if "moe" in list:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; do if moe is in list<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br><br>R) dict<br>&nbsp;&nbsp; mydict = {key1:value1,key2:value2}<br>&nbsp;&nbsp; mydict = {}<br>&nbsp;&nbsp; usage: myvar = mydict[key1];<br>&nbsp;&nbsp; mykeys = mydict.keys();<br>&nbsp;&nbsp; myvalues = mydict.values();<br>&nbsp;&nbsp; myitems = mydict.items();&nbsp; // tuple<br>&nbsp;&nbsp; for k,v in myitems : print (k,"=",v)<br>&nbsp;&nbsp; s = : %(word)s %mydict<br>&nbsp;&nbsp; del mydict[0];<br>&nbsp;&nbsp; del mydict[-2:0]<br><br>S) files<br>&nbsp;&nbsp; #open file<br>&nbsp;&nbsp; f = fopen("filaneme.txt", "rt", encoding='utf-8')<br>&nbsp;&nbsp; for line in f:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print (line, end='')<br>&nbsp;&nbsp; f.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br><br>T) regular expressions<br>&nbsp;&nbsp; import re<br>&nbsp;&nbsp; mystr = " hello 123 456";<br>&nbsp;&nbsp; mymatch = re.search(mystr, '\d+');<br>&nbsp;&nbsp; mymatch = re.findall(mystr, "\d+");<br>&nbsp;&nbsp; mymatch = re.sub(mystr, "123", "\d+");<br><br>U) major important libraries<br>&nbsp;&nbsp; os lib: os.listdir(dir), os.path.join(dir,filename), os.path.abspath(filename), os.path.dirname(filename)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.path.basename(filename), os.path.exists(filename), os.mkdir(path), os.mkdirs(path1)<br>&nbsp;&nbsp; shutil lib: shutil.copy(source,target)<br>&nbsp;&nbsp; subprocess:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) -<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subprocess.popen<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subprocess.call<br>&nbsp;&nbsp; urilib lib:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ufile = urllib.request.urlopen(url);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; text = ufile.read()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info = ufile.info()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; baseurl = ufile.geturl()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; urllib.request.urlretrieve(url, filename)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; urllib.parse.urljoin(baseurl, url)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from urllib.request import urlopen<br>&nbsp;&nbsp; uriparse lib:<br><br><br>]]></description>
</item>
<item rdf:about="/blog/view/8">
<title>bootstrap</title>
<link>/blog/view/8</link>
<dc:date>2024-03-01</dc:date>
<description><![CDATA[Basic Bootstrap Cheatsheet:<br>---------------------------<br>Get Bootstrap css from:<br>https://getbootstrap.com<br><br><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><br><br>Start container css:<br>container-fluid<br><br><br>Button CSS classes:<br>btn (every button gets this)<br>btn-default btn-info btn-danger (various colors set)<br>btn-block (block instead of inline)<br><br>Shading classes:<br>well <br><br>Text css:<br>text-primary<br>text-center<br><br>rows:<br><code><p class="row"><br>   </p><p class="col-xs-6"><br>   </p><br>   <p class="col-xs-3"><br>   </p><br>   <p class="col-xs-3"><br>   </p><br><p></p><br><br>container has class row<br>row as 12 cols<br>col-xs-3 - means column, extra small, 3 columns<br><br>Extras:<br>------<br>Full Cheat Sheet:<br>https://hackerthemes.com/bootstrap-cheatsheet/<br><br></code>]]></description>
</item>
<item rdf:about="/blog/view/9">
<title>sass</title>
<link>/blog/view/9</link>
<dc:date>2024-02-22</dc:date>
<description><![CDATA[SASS Cheat Sheet - Syntactically Awesome Style Sheets<br><br>Use type: text/scss on the style tag<br><br>&lt;style type='text/scss'&gt;<br>&lt;/style&gt;<br><br>Define a variable:<br>$varname: value;<br>&nbsp; Sample:&nbsp; $text-color:red<br><br>Nesting css elements<br>.foo {<br>&nbsp;&nbsp;&nbsp;&nbsp; p {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; color:red;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; }<br><br>mixins:<br>--------<br>Define:<br>@mixin funcname($arg1, $arg2) {<br>&nbsp;&nbsp; blah($arg1);<br>}<br>Use:<br>@include funcname("blah","blah2");<br><br>In mixins - conditionals<br>@if $val == foo<br>@else if $val == blah<br>@else<br><br>looping:<br>@for $var from 1 through 6 {<br>&nbsp;&nbsp; .classname-#{$var} { font-size: 15 * $var}<br>}<br>loop over list:<br>@each $var in blue,green,red {<br>&nbsp;&nbsp; .#{$var}-text { color: $var; }<br>}<br><br>while statement:<br>$var : 0;<br>@while $var &lt; foo {<br>&nbsp;&nbsp; .column-#{$var} { font-size: 12 * $var;}<br>&nbsp;&nbsp;&nbsp; $var: $var +1;<br>}<br><br>import partials:<br>@import "filename"<br>_filename.scss would be file.<br><br>extend:<br>@extends .otherrule<br><br><br>]]></description>
</item>
<item rdf:about="/blog/view/10">
<title>jquery</title>
<link>/blog/view/10</link>
<dc:date>2024-02-22</dc:date>
<description><![CDATA[Basic Jquery Cheatsheet:<br><br>Get it from:<br>https://jquery.com/download<br><br>Run on Load<br>&lt;script&gt;<br>$(document).ready(function() {<br>});<br>&lt;/script&gt;<br><br>Reference a type (e.g. a button)<br>$("typename").addClass("foo");<br><br>Reference a class:<br>$(".classname").addClass("foo");<br><br>Reference an id:<br>$("#idname").addClass("foo");<br><br>Functions:<br>----------<br>css - add css rule to element<br>&nbsp;&nbsp; Sample $(#myid).css('background-color','red');<br>&nbsp;&nbsp; Note that its a comma between elements, not a colon<br>addClass - adds a class to an element<br>removeClass -removes a class from an element<br>html - sets body of element<br>text - set element text without evaluating<br>remove - removes an element<br>appendTo - appends selected element to new target<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sample: $("#myid").appendTo("#target2");<br>clone - create a clone<br>&nbsp;&nbsp;&nbsp;&nbsp; Sample: $("#myid").clone().appendTo("#target2");<br>parent - finds parent element of element selected.<br>children - finds children elements of element selected.<br>nth-child - finds nth child of element<br><br>]]></description>
</item>
<item rdf:about="/blog/view/11">
<title>node.js</title>
<link>/blog/view/11</link>
<dc:date>2024-03-01</dc:date>
<description><![CDATA[1. bun is a replacement for node.js<br>   https://bun.sh<br><br>2. generally nodejs is installed via yum, dnf, or whatever package<br>   manager you have<br><br>3. node.js is javascript engine that runs javascript on the server side<br><br>4. To setup a project<br>   npm init<br><br>5. install express server<br>   npm install express --save<br>   see https://expressjs.com<br><br>6. Here is "Hello World!" using an express server<br>  See https://expressjs.com<br>  <br>const express = require('express')<br>const app = express()<br>const port = 3000<br><br>##<br>## App get sets a route for /<br>app.get('/', (req, res) => {<br>  res.send('Hello World!')<br>})<br><br>app.listen(port, () => {<br>  console.log(`Example app listening on port ${port}`)<br>})<br><br>7. BUT - really nobody uses the simple version...<br>   we use express-generator<br>   # install express-generator<br>   >npm install -g express-generator<br>   # run install<br>   >express<br><br>   This generates a structure in the current directory including:<br>   routes<br>   views<br>   bin<br>   public <br>   node_modules<br><br>   a) public is for static html files<br><br>   b) routes defines how to route urls<br><br>   c) bin<br>      bin/www is what starts the server<br>      <br>8. nodemon - sets up node so that it will reread files<br>   upon change.<br>   > npm install --save-dev nodemon<br>   <br>9. Fetching data from the database.<br>   a) create an object that fetches data ( file con.js)<br>   <br>   var mysql = require('mysql2');<br>   var con = mysql.createConnection({<br>           host:'localhost',<br>           user: 'xxxxxuser',<br>       password:'yyyypass',<br>       database:'foodb'<br>   });<br><br><br>   con.connect(function(err) {<br>      if (err) throw err;<br>   });<br><br>   async function sqlquery(sql)<br>   {<br>      const results = await con.promise().query(sql);<br>     // returns a list of [data,meta] <br>      return results[0];<br>   }<br><br>   module.exports = {<br>       sqlquery<br>   }<br><br>   b) from routes/index.js<br>     var con = require("../services/con");<br>     router.get('/fubar', async function(req,res,next) {<br>        let sql = 'show tables';                   <br>        res.json(await con.sqlquery(sql));                   <br>     });<br><br>  c) await can only be used from an aync function<br>     the function being called needs to be async<br>     and we do an await on a promise from con.query...<br>     the results returned are a list of elements, data, and meta data<br>     This appears complex.<br>     basically the mysql query is run in the background unless<br>     we force nodejs to wait for the results<br>     <br>     <br><br>]]></description>
</item>
<item rdf:about="/blog/view/12">
<title>react</title>
<link>/blog/view/12</link>
<dc:date>2024-02-22</dc:date>
<description><![CDATA[1. you can run react direct in a standard html file<br>&nbsp;&nbsp;&nbsp; https://www.w3schools.com/react/react_getstarted.asp<br><br>2. Or create a react.js app<br>&nbsp;&nbsp; -- npm install -g create-react-app<br>&nbsp;&nbsp; -- npx create-react-app my-app-name<br>&nbsp;&nbsp; -- npm start - will start app on port 3000<br>&nbsp;&nbsp; -- edit package.json to redirect port<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; under scripts section in package.json<br>&nbsp;&nbsp; &nbsp;change "start": "PORT=9561 react-scripts start",<br>&nbsp;&nbsp; -- this is a development version<br>&nbsp;&nbsp; -- can redirect apache with<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProxyPass / http://localhost:9561/<br>&nbsp;&nbsp; -- the sample app created expects the app to be at the top level<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.g. react.mindcontract.com<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The paths are not set up to allow a subdir app.<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br><br>&nbsp; &nbsp;<br>react.js cheatsheet<br><br>From facebook.<br><br>Babel transpiler translates react.js to html/css<br><br>Command that puts JSX on DOM<br>ReactDOM.render(JSX, document.getElementById('root'))<br><br>When defining a JSX must return a complete element<br><br>comments:<br>{/* comments here&nbsp; */}<br><br>ReactDOM api renders JSX to HTMLDOM<br>ReactDOM.render(componentToRender, targetNode)<br><br>use className instead of class on elements<br><br>Components:<br>1. components start with Capital letter<br>2. must return element or null<br>3. stateless <br>const MyComponent = function () {<br>&nbsp;&nbsp;&nbsp; return (<br>&nbsp;&nbsp; &nbsp;&lt;div&gt;foo&lt;/div&gt;<br>&nbsp;&nbsp;&nbsp; )<br>}<br><br>4. ES6 format - extend from React.Component<br>class MyComponent extends React.Component {<br>&nbsp; constructor(props) {<br>&nbsp;&nbsp;&nbsp; super(props);<br>&nbsp; }<br><br>&nbsp; render() {<br>&nbsp;&nbsp;&nbsp; return (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;h1&gt;Hi&lt;/h1&gt;<br>&nbsp;&nbsp;&nbsp; );<br>&nbsp; }<br>}<br><br>const ChildComponent = () =&gt; {<br>&nbsp;&nbsp;&nbsp; return (<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &lt;div&gt;hello&lt;/div&gt;<br>&nbsp;&nbsp;&nbsp; );<br>}<br><br>Composition<br>-----------<br>Once you define a component, compose with &lt;NameComponent arg="foo" /&gt;<br>&nbsp;&nbsp;&nbsp; ${props.foo} is the value.<br>&nbsp;&nbsp; &nbsp;<br><br>import PropTypes from 'prop-types';<br><br>]]></description>
</item>
<item rdf:about="/blog/view/13">
<title>laravel</title>
<link>/blog/view/13</link>
<dc:date>2024-03-22</dc:date>
<description><![CDATA[1a. laravel required sqlite.<br>    > dnf install sqlite-devel<br>1b. To create a laravel project<br>    > composer create-project laravel/laravel:^11.0 project-name<br><br>2. So laravel when developing is generally done by running a local<br>   web server, which listens on port 8000.  From your project directory<br>   >  php artisan serve<br>   Now point your browser at http://localhost:8000<br><br>3. in the app:<br>   config directory - has configuration files.<br>       (app.php is main one)<br><br><br><br>4. So I chose to use postgres to use as a database.<br><br>A. create user and database<br>   > sudo -u postgres psql<br>   > create user foo password 'bar';<br>   > create database fubardb owner foo;<br><br>configure postgresql in .env in top level of project<br><br>DB_CONNECTION=pgsql<br>DB_HOST=127.0.0.1<br>DB_PORT=5432<br>DB_DATABASE=fubardb<br>DB_USERNAME=foo<br>DB_PASSWORD=bar<br><br>configure /var/lib/pgsql/data/pg_hba.conf<br>change the line for for ipv4 to:<br>(ident needs to change to trust)<br>host    all             all             127.0.0.1/32            trust<br><br>5. So this doesn't work...<br>   need to compile pgsql, and/or mysql<br>   So php needs to be compiled with flags<br>   ./configure --with-pdo-mysql=mysqlnd \<br>       --with-pdo-pgsql=mysqlnd \<br>       --with-pgsql \<br>       --with-mysqli<br><br>   // Laravel uses the PDO objects in its database access.<br><br>6. run php artisan migrate:fresh<br>   this generates the user account handling stuff for laravel<br>   <br><br>7. Routes are in the routes subdiretory<br>   routes/web.php<br><br>   To add an api<br>   php artisan install:api<br>   This generates routes/api.php<br>   <br>8. Creating a table in Laravel - Migration<br>   > php artisan make:migration migration_name<br><br>   This creates a php object datestamped, with the migration name in<br>   database/migrations<br><br>   The object has an up and down function.<br>   So to create the table update the up function.<br>   <br>
<code>
   <br>public function up(): void<br>    {<br>        Schema::create('cave', function (Blueprint $table) {<br>            $table->id();<br>            $table->string('name');<br>            $table->text("description");<br>            $table->string("city");<br>            $table->string('county');<br>            $table->string('state');<br>            $table->text("directions");<br>            $table->datetime("created");<br>            $table->string("source");<br>            $table->string("gps");<br>            $table->string("altitude");<br>            $table->string("depth");<br>            $table->string("length");<br>            $table->string("managedby");<br>            $table->string("area");<br>            $table->string("landowner");<br>            $table->timestamps();<br>        });<br>        <br>    }<br>
</code>    <br><br>   <br><br>]]></description>
</item>
<item rdf:about="/blog/view/14">
<title>perl</title>
<link>/blog/view/14</link>
<dc:date>2024-03-25</dc:date>
<description><![CDATA[1. mod_perl<br><br>2. variables<br><code><br>   my $name = "value";<br>   my %hash = ( "blah"=>"foo",<br>                    "base"=>"path");<br>   print $hash{"blah"};<br>   <br>   my @array = ("a","b","c");                <br>   print $array[1];<br></code>   <br><br>3. comparators:<br># Numerical operators:  <,  >, <=, >=, ==, !=, <=>, +, *<br># String operators:    lt, gt, le, ge, eq, ne, cmp, ., x<br><br>4.<br><code><br>unless ($foo > 3)<br>   {<br>      print "foo";<br>   }<br>   else<br>   {<br>      print "blah";<br>   }<br></code><br>5. if, elsif,else<br><br>   $foo = 10 if ($blah == 4);<br><br>6. ?:<br><code><br>   $blah =  ($foo==1) ? "one":"two";<br>   <br>7. for (my $i=0;$i<10;$i++)<br>{<br>}<br>   foreach my $blah (@reverse)<br>   {<br>    print $blah."\n";<br>   }<br></code><br>8. keys %hash - to get keys of hash<br><br>9. next, last can be used in loops..<br>   equivalent to continue, and break<br><br><br>10. pop,<br>    push,<br>    shift,<br>    unshift<br>    splice<br>    join<br>    grep<br>    <br>11. my $rc = system "perl", "foo.pl";<br>     $rc >>= 8;<br>    print "Status Code:".$c."\n";<br><br><br>    my @lines = `perl foo.pl`;<br><br>    exit 37;<br><br><br>12. files<br>    my $filename= "text.txt";<br>    my $result = open my $handle, "<", $filename;<br><br>    if (!$result)<br>       {<br>      die "Failed to open ".$filename." because, $!;<br>       }<br><br>    open (my $handle, "<", $filename) || die "failed ".$!."\n";<br><br>13. while (!eof $handle)<br>    {<br>    my $line = readline $fh;<br>    }<br><br>14. while (my $line = readline $handle)<br>   {<br>   }<br><br>   while (my $line = <$handle>)<br>   {<br>   }<br><br>   while (<$handle>)<br>        {<br>        print $_;<br>     }<br><br>15. -e<br>    -d<br>    -f<br>    <br><br>16. regex<br>    <br>    if (  $hello =~ m/(\w+)\s+(\w)/)<br>         echo $1." ".$2;<br>     <br>    replace $foo =~ s/blah/foo/g;<br>       // g is global<br>       <br><br><br>17. modules.<br>    1) must return 1 in .pl file<br>    2) require "Demo::module_name";<br>         (comes from subdir Demo/module_name.pl)<br>    3) PERL5LIBS=blah<br><br>      <br>    <br><br>]]></description>
</item>
<item rdf:about="/blog/view/15">
<title>postgres</title>
<link>/blog/view/15</link>
<dc:date>2024-03-22</dc:date>
<description><![CDATA[1. install postgres<br>&nbsp;&nbsp; dnf install postgresql-server<br>&nbsp;&nbsp; dnf install postgresql-contribb<br>&nbsp;&nbsp; dnf install postgresql-devel<br>&nbsp; &nbsp;<br>2. &gt;systemctl enable postgresql<br><br><br>3. need to initialize postgres<br>&nbsp;&nbsp; &gt;postgresql-setup --initdb --unit postgresql<br>&nbsp; &nbsp;<br>4. start the server<br>&nbsp;&nbsp; &gt; systemctl start postgresql<br><br>5. Now get command line access<br>&nbsp;&nbsp; sudo -u postgres psql<br><br>6. The command line now allows sql commands<br>&nbsp;&nbsp; a. CREATE USER<br>&nbsp;&nbsp;&nbsp;&nbsp; =# create user USERNAME with password 'PASSWORD';<br><br>&nbsp;&nbsp; b. CREATE DATABASE DBNAME OWNER 'USERNAME'<br><br>&nbsp;&nbsp; c. su postgres<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; psql DBNAME<br><br>7. recomping php with flag --with-pgsql on configure script<br>&nbsp;&nbsp; include --with-pdo-pgsql (laravel uses that)<br>&nbsp;&nbsp; <br>]]></description>
</item>
<item rdf:about="/blog/view/16">
<title>Laravel II</title>
<link>/blog/view/16</link>
<dc:date>2024-03-25</dc:date>
<description><![CDATA[1. So you can install laravel globally<br>&lt;code&gt;<br>composer global require laravel/installation<br>&lt;/code&gt;<br>This installs the laravel binary in ${HOME}/.config/composer/vendor/bin<br>Its useful to put this as a separate user. I chose &lt;b&gt;composer&lt;/b&gt;<br>&lt;code&gt;<br>useradd composer<br>su - composer<br>composer global require laravel/installation<br>chmod 777 /home/composer<br>&lt;/code&gt;<br>So other users can use the laravel installation binary, add the location to<br>Path. edit /etc/profile.d/local.sh<br>&lt;code&gt;<br>export PATH=$PATH:/home/composer/.config/composer/vendor/bin<br>&lt;/code&gt;<br><br>2. starter kits.&nbsp;&nbsp; So following a tutorial for laravel, and as usual its out of data.&nbsp;&nbsp; So to create a project:<br>&lt;code&gt;<br>laravel new posty<br>&lt;/code&gt;<br>And now it asks me for a "starter kit"<br>None, Breeze, Jetstream.<br>I chose None<br><br>And now it asks me the testing framework<br>Pest, or PHPUnit<br>I chose Pest - it was the default<br>And now whether I want to initialize a git repository<br><br>And now it asks me for what database to use<br>Mysql, Mariadb, PostgresSQl, SQLite, SQL Server<br><br>3. &lt;b&gt;php artisan&lt;/b&gt; lists all the various things you can<br>do with artisan e.g. laravel<br><br>4. So &lt;b&gt;blade&lt;/b&gt; The laravel default template engine.<br>&nbsp;&nbsp; First thing is to be introduced to Layouts....<br>&nbsp;&nbsp; a. php artisan make:component Layout<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this generates a Layout component with<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // resources/views/controller/layout.blade.php<br>&nbsp;&nbsp;&nbsp; b. Here is a sample layout controller (resoure/views/controller/layout.blade.php<br>&nbsp;&nbsp;&nbsp; &lt;code&gt;<br>&nbsp;&nbsp;&nbsp; &lt;pre&gt;<br>&nbsp;&nbsp;&nbsp; &lt;html&gt;<br>&nbsp; &lt;head&gt;<br>&nbsp;&nbsp;&nbsp; &lt;title&gt;{{ $title ?? 'Example Website' }}&lt;/title&gt;<br>&nbsp;&nbsp;&nbsp; &lt;link rel="stylesheet" href="{{ asset('/css/app.css') }}"&gt;<br>&nbsp; &lt;/head&gt;<br>&nbsp; &lt;body&gt;<br>&nbsp;&nbsp;&nbsp; &lt;nav&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;h3&gt;Welcome to my website&lt;/h3&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;hr&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/nav&gt;<br>&nbsp;&nbsp;&nbsp; {{ $slot }}<br>&nbsp;&nbsp;&nbsp; &lt;footer&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;hr /&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;copy; 2023 example.com<br>&nbsp;&nbsp;&nbsp; &lt;/footer&gt;<br>&nbsp; &lt;/body&gt;<br>&lt;/html&gt;<br>&lt;/pre&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/code&gt;<br><br>c. So a content php file is called a view.<br>&nbsp;&nbsp;&nbsp; each file view is named viewname.blade.php<br>&nbsp;&nbsp; example welcome.blade.php<br><br>d. Sample welcome.blade.php<br>&nbsp;&nbsp; &lt;code&gt;<br>&nbsp; &nbsp;<br>&nbsp;&nbsp; &lt;pre&gt;<br>&lt;x-layout&gt;<br>&nbsp;&nbsp; &lt;x-slot name="title"&gt;<br>&nbsp;&nbsp;&nbsp; Home | Example Website<br>&nbsp; &lt;/x-slot&gt;<br>&nbsp; &lt;div&gt;<br>&nbsp;&nbsp; &nbsp;&lt;h1&gt;Hello World!&lt;/h1&gt;<br>&nbsp;&nbsp; &nbsp;&lt;p&gt;Lorem ipsum dolor sit amet consectetur adipiscing elit. Hic, aut?&lt;/p&gt;<br>&nbsp;&nbsp;&nbsp; &lt;button class="btn"&gt;Get Started&lt;/button&gt;<br>&nbsp; &lt;/div&gt;<br>&lt;/x-layout&gt;<br>&lt;/pre&gt;<br>&lt;/code&gt;<br>&nbsp;&nbsp;&nbsp; the magic &lt;b&gt;x-layout&lt;/b&gt; tag tells the template to use the layout<br>&nbsp;&nbsp;&nbsp; component<br>&nbsp;&nbsp;&nbsp; the &lt;b&gt;x-slot&lt;/b&gt; tag lets you pass alternate content to the layout<br>&nbsp;&nbsp;&nbsp; the code {{ $title ?? 'Example Website' }} says to show the variable<br>&nbsp;&nbsp;&nbsp; title if it exists otherwise "Example Website"<br>&nbsp;&nbsp;&nbsp; The x-slot allows you to overlayout that.<br><br>5. tailwindcss.&nbsp; Install via npm<br>&lt;code&gt;<br>npm install tailwindcss<br>&lt;/code&gt;<br>So... an aside, you will see warnings on npm if you are pulling from<br>the http vs https registry.&nbsp; You can configure your registry in npm<br><br>&lt;code&gt;<br>npm config set registry https://registry.npmjs.org/<br>&lt;/code&gt;<br><br>6. I use emacs... but all the samples use code visual studio<br>&nbsp;Download from https://code.visualstudio.com/Download<br><br>7. models, controllers and crud oh my.<br><br>&nbsp;&nbsp; So by default the laravel resource code for controllers<br>&nbsp;&nbsp; doesn't handle POSTs well.<br><br>&nbsp;&nbsp; So - you make a model<br>&nbsp;&nbsp; php artisan make:model Product<br>&nbsp;&nbsp; php artisan make:controller ProductController --resource<br>&nbsp; &nbsp;<br>&nbsp;&nbsp; So if you use<br>&nbsp;&nbsp; Router::resource("product", ProductController::class);<br>&nbsp;&nbsp; you can't just use POST from your html form post.<br>&nbsp;&nbsp; from the docs its supposed to be PUT method, but PUT method<br>&nbsp;&nbsp; makes the fields passed as a url - which means you hit a limitation<br>&nbsp;&nbsp; method on requests where the content is over a certain limit.<br><br>&nbsp;&nbsp; So vendor/laravel/framework/src/Illuminate/Routing/ResourceRegistrar.php<br>&nbsp;&nbsp; line 493, add "POST" in the methods that can match.<br><br>&nbsp;&nbsp; So now you can use POST. really stupid.. I ended up having to chance<br>&nbsp;&nbsp; down where it matches the code in laravel. 2 1/2 hours later.<br><br>&nbsp;&nbsp; Unbelievable the number of simple projects that purport to show<br>&nbsp;&nbsp; a simple crud example in laravel.&nbsp;&nbsp; Half of them do not have<br>&nbsp;&nbsp; the routing information provided.&nbsp;&nbsp; Some clearly are from previous<br>&nbsp;&nbsp; versions of laravel.<br><br>&nbsp;&nbsp; It would be really nice if it wrote the actual functions in the<br>&nbsp;&nbsp; controller when you do --resource<br><br>]]></description>
</item>
<item rdf:about="/blog/view/17">
<title>Inbound Mail AWS</title>
<link>/blog/view/17</link>
<dc:date>2024-04-10</dc:date>
<description><![CDATA[<p>If you set up an aws EC2 instance and use an elastic IP - the incoming smtp is blocked.</p><p>Don't let anyone kid you - its a fact.    It doesn't matter if you adjust your security group</p>
<p>to allow incoming smtp.</p>
<p><br></p><p>So what is the alternative?</p>
<p><br></p><p>The answer I came up with today is forwardemail.net</p><p><br></p>
<p>It allows you to assign mx servers and route your email.</p>
<p>It allows you to route to a specific mailbox AND, AND, AND it allows you to setup</p>
<p>a webhook to post to when emails are sent.</p>
<p><br></p><p>A webhook is a piece of code on a server that accepts a payload.</p>
<p>In this case its a json with the wad of an email each time that someone sends an email</p><p>to a particular domain.</p>
<p><br></p>
<p>The documentation from forwardemail.net on the particular json packet sent is non <br></p><p>existent - but it doesn't matter once you see the json.</p>
<p><br></p>
<p>Ok - so once you get the wad of json - the next thing is to parse the email.</p>
<p>Again this is a piece of arcana that is a bit weak on documentation. <br></p>
<p><br></p>
<p>1. php has mailparse - this is a pecl addition to parse mime emails.</p><p><br></p><p>2. there is a library that uses the pecl library mailparse.</p>

<p>    php-mime-mail-parser is a php library that supposedly is supported for php 8+</p>
<p><br></p>
<p>And if you are going to mess with this stuff believe me, you want to be able to have</p>
<p>baseline to test emails with:</p>
<p><br></p>
<p>Here is a link to a really solid tool to send emails:</p>
<p><br></p><p>https://sendtestemail.com<br></p>
<p><br></p>
<p>Ok, don't forget the implications of a) SPF b) DKIM C) DMARC D) Reverse DNS<br></p>
<p><br></p><p>Here is sample code for a webhook from forwardemail.net that seems to work.</p><p>The code depends on a bunch of other stuff - but it should be a good start in <br></p>
<p>allowing you to grab the data.</p>
<p><br></p>
<p></p>
<p>

<code>function do_inject($path)<br>  {<br>      header('Content-Type: application/json');<br>      $request = file_get_contents('php://input');<br><br>      $rand = rand(1000,2000);<br>      $raw ="/m/member/tmp/incoming.".$rand.".email";<br>      $parsed = "/m/member/tmp/incoming.".$rand.".parsed";<br>      file_put_contents($raw,$request);<br>      require_once "parseinject.php";<br>      $pi = new parseinject();<br>      $fields = $pi->parse($request);<br>      $emailparsed = "";<br>      foreach ($fields as $key=>$value)<br>      {<br>          $emailparsed .= $key."\n";<br>          $emailparsed .= $value."\n";<br>          $emailparsed .= "\n";<br>          $emailparsed .= "\n";<br>      }<br>      file_put_contents($parsed,$emailparsed);<br>      require_once "background/injector/injectmail.php";<br>      $imail =new injectmail();<br>      $imail->source_email = $fields['from'];<br>      $imail->target_email = $fields['address'];<br>      $imail->email_content = $fields['raw'];<br>      $imail->email_size = strlen($fields['html']);<br>      $imail->queue_reference = $field['messageid'];<br>      $imail->ship2queue();<br>      echo "INJECTED";<br>      http_response_code(200);
}<br></code>
</p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>
<p><br></p>]]></description>
</item>
<item rdf:about="/blog/view/18">
<title>mongodb II</title>
<link>/blog/view/18</link>
<dc:date>2024-04-12</dc:date>
<description><![CDATA[<p>Installation on aws 2023 /aws 2</p><p><br></p><p>So the general advice on the net is to do:<br></p><p>dnf install mongodb-org</p><p><br></p><p>When you get to mongosh ... you lose...</p><p>You'll get an error like:</p><p>&lt;code&gt;</p><p>[root@groupcorners /]# mongosh<br>mongosh: OpenSSL configuration error:<br>40C88FFB977F0000:error:030000A9:digital envelope routines:alg_module_init:unkno\<br>wn option:../deps/openssl/openssl/crypto/evp/evp_cnf.c:61:name=rh-allow-sha1-si\<br>gnatures, value=yes<br>&lt;/code&gt;<br></p><p><br></p><p>And its all very sad!</p><p><br></p><p>So... to fix this:</p><p>&lt;code&gt;<br></p><p>dnf remove mongdb-org</p><p>dnf install ongodb-mongosh-shared-openssl3</p><p>dnf install mongodb-org</p><p>&lt;/code&gt;<br></p><p>Somehow installing mongdb-org straight gets the wrong version of mongosh installed.</p><p>No one likes dependencies.</p><p><br></p><p>Now at least mongosh works.&nbsp; Wish I knew where to send this bit so it gets fixed!<br></p>]]></description>
</item>
</rdf:RDF>