Categories
Programming Uncategorized

SFTP/FTP Project uploader

This program uploads files and directories from your local machine to a remote server using either SFTP or FTP, based on the protocol specified in the configuration file.

Download here: mProjectUploader.zip

Features

  • Supports both SFTP (Secure Shell) and FTP (File Transfer Protocol).
  • Automatically handles directory creation on the remote server.
  • Skip files or directories based on configurable patterns.
  • Multiple overwrite policies, including:
    • skipAll: Skip all existing files.
    • overwriteOlder: Overwrite files only if the remote file is older.
    • overwriteDifferentSize: Overwrite files if their sizes differ.
    • overwriteAll: Overwrite all files.
    • OverwriteKeepTrack: Overwrite only if the file content has changed (based on checksum).
  • Tracks skipped, changed, and uploaded files.

Usage Instructions

1. Prepare the Configuration File

The program uses an XML configuration file (e.g., config.xml) to define its behavior. Below is an example of the configuration file:

<config>
<protocol>sftp</protocol> <!-- Use 'sftp' or 'ftp' -->
<host>example.com</host>
<port>22</port> <!-- Default: 22 for SFTP, 21 for FTP -->
<username>your_username</username>
<password>your_password</password>
<destinationPath>/remote/destination/folder</destinationPath>
<overwritePolicy>OverwriteKeepTrack</overwritePolicy>
<skipList>
<file>*.tmp</file> <!-- Skip all .tmp files -->
<file>*.log</file> <!-- Skip all .log files -->
<directory>node_modules</directory> <!-- Skip this directory -->
</skipList>
<checksums>
<!-- Checksum tracking for OverwriteKeepTrack -->
<file path="local/path/to/file1.txt" checksum="abc123" />
<file path="local/path/to/file2.txt" checksum="def456" />
</checksums>
</config>

2. Run the Program

Run the program using the following command:

SftpUploader.exe <config_file_path>

For example:

SftpUploader.exe config.xml

If no configuration file path is provided, the program looks for config.xml in the current directory.


Configuration Parameters

General Settings

  • <protocol>: Specifies the transfer protocol. Options:
    • sftp: Secure Shell File Transfer Protocol.
    • ftp: File Transfer Protocol.
  • <host>: Remote server hostname or IP address.
  • <port>: Server port (default: 22 for SFTP, 21 for FTP).
  • <username>: Username for authentication.
  • <password>: Password for authentication.
  • <destinationPath>: Remote directory path(s). Multiple <destinationPath> entries are supported.

File Handling

  • <overwritePolicy>: Determines how existing files are handled. Options:
    • skipAll: Skip all files that exist on the server.
    • overwriteOlder: Overwrite files only if the remote file is older.
    • overwriteDifferentSize: Overwrite files if their sizes differ.
    • overwriteAll: Overwrite all files.
    • OverwriteKeepTrack: Overwrite files only if their content has changed. Uses checksums stored in the checksums section.

Skip List

  • <skipList>: Allows you to exclude specific files or directories from processing.
    • <file>: Wildcard patterns for files to skip (e.g., *.log, *.tmp).
    • <directory>: Names of directories to skip.

Checksum Tracking

  • <checksums>: Used with OverwriteKeepTrack to track file changes.
    • <file>: Each entry contains the local file path and its checksum.

Features Based on Protocol

SFTP

  • Fully secure file transfer using SSH.
  • Handles recursive directory creation via the CreateDirectoryRecursively method.

FTP

  • Classic FTP protocol with directory and file handling.
  • Uses System.Net.FtpWebRequest for file uploads and directory creation.

Example Scenarios

1. Upload All Files

<overwritePolicy>overwriteAll</overwritePolicy>

This policy overwrites all files on the remote server.

2. Skip All Files

<overwritePolicy>skipAll</overwritePolicy>

This policy skips all files that already exist on the server.

3. Upload Only Changed Files

<overwritePolicy>OverwriteKeepTrack</overwritePolicy>

This policy compares checksums and uploads only files that have changed.

4. Skip Specific Files and Folders

<skipList>
<file>*.tmp</file>
<directory>bin</directory>
</skipList>

This configuration skips all .tmp files and the bin directory.


Statistics

At the end of execution, the program outputs statistics about the operation:

  • Total Files: The total number of files considered.
  • Skipped Files: The number of files skipped based on the policy or skip list.
  • Changed Files: The number of files identified as changed (only for OverwriteKeepTrack).
  • Uploaded Files: The number of files successfully uploaded.

Example output:

Processing destination: /remote/destination/folder
Total Files: 50, Skipped Files: 20, Changed Files: 5, Uploaded Files: 25

Error Handling

  • If the configuration file is missing or invalid, the program will display an error and exit.
  • Errors during file uploads or directory creation are logged to the console but do not stop the program.

Dependencies

  • SFTP: Renci.SshNet library for secure file transfer.
  • FTP: Built-in System.Net.FtpWebRequest.

Troubleshooting

  1. Missing Configuration File: Ensure the configuration file exists at the specified path and follows the correct format.
  2. Protocol Not Supported: Verify the <protocol> field in the configuration file is set to ftp or sftp.
  3. Authentication Issues: Check the host, username, and password values in the configuration file.
  4. Skipped Files: Review the <skipList> and <overwritePolicy> settings to ensure they align with your expectations.
Categories
Uncategorized

Outlook automapped mailboxes – dealing with design flaws with VBA

Sending an email from a automapped (usually shared) mailboxes – I don’t know why, because everyone hates that – has two issues: 1. user needs to change From address every time from his primary mailbox to the correct one, 2. Sent emails are saved in primary mailbox Sent folder, not in the folder of the shared mailbox.

We want Outlook to use From address based on selected folder in Outlook and also, we want this email to be saved in correct Sent folder. This issue has been present ever since and MS approach to first spit out registry hacks and then enable setting some parameters – only for each Mailbox separately (!) to deal with issue #2 is unacceptable. As usually we need to make some hacks to fix that.

Private WithEvents objInspectors As Outlook.Inspectors
Private WithEvents sentItems As Outlook.Items

Function findAddressOfCurrentFolder()
        Set selectedFolder = Application.ActiveExplorer.CurrentFolder
        
        ' Initialize the Outlook NameSpace
        Set namespace = Application.GetNamespace("MAPI")
        Set Stores = namespace.Stores
        storeDisplayName = selectedFolder.Parent.Store.DisplayName
        Set storeRecipient = Session.CreateRecipient(storeDisplayName)

        If storeRecipient.AddressEntry.Type = "EX" Then
            findAddressOfCurrentFolder = storeRecipient.AddressEntry.GetExchangeUser.PrimarySmtpAddress
            
        End If
        If storeRecipient.AddressEntry.Type = "SMTP" Then
            findAddressOfCurrentFolder = storeRecipient.Address
        End If
End Function

Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)

  If TypeName(Inspector.CurrentItem) = "MailItem" Then
     storeSMTPAddress = findAddressOfCurrentFolder
     If storeSMTPAddress <> "" Then 
        Inspector.CurrentItem.SentOnBehalfOfName = storeSMTPAddress
     End If
  End If
End Sub

We just fixed the first issue! One more to go.

Function isSentItemsFolder(ByVal Folder As Outlook.Folder)
 sentFolderNames = Array("Sent Items", "Odeslaná pošta", "Odoslaná pošta")
 For i = LBound(sentFolderNames) To UBound(sentFolderNames)
        If sentFolderNames(i) = Folder.Name Then
            isSentItemsFolder = True
            Exit Function
        End If
    Next i
 isSentItemsFolder = False
End Function
Private Sub sentItems_ItemAdd(ByVal Item As Object)
 Dim correctSentFolder As Outlook.Folder
 Dim myNamespace As Outlook.namespace
 Dim mailbox As Outlook.MAPIFolder
 
    If TypeName(Item) = "MailItem" Then     'If Item is a MailItem
        If Item.SentOnBehalfOfName <> Session.Accounts.Item(1).CurrentUser Then   'And if Item is Sent on Behalf of the users own inbox
            'Move the email into the Sent Items folder for the inbox in question
            Set myNamespace = Application.GetNamespace("MAPI")
            Set myRecipient = GetNamespace("MAPI").CreateRecipient(Item.SentOnBehalfOfName)
            myRecipient.Resolve
            If myRecipient.Resolved Then
                'Set sentFolder = GetNamespace("MAPI").GetSharedDefaultFolder(myRecipient, olFolderSentMail)
                Set mailbox = myNamespace.GetSharedDefaultFolder(myRecipient, olFolderInbox).Parent
                For Each Folder In mailbox.Folders
                    If Folder.DefaultItemType = olMailItem Then
                     If (isSentItemsFolder(Folder)) Then
                        Set correctSentFolder = Folder
                    End If
                 End If
                Next Folder
            End If
            If Not correctSentFolder Is Nothing Then Item.Move correctSentFolder
        End If
        
    End If
End Sub

And that’s the fix for the second issue – saving items in proper folder. There is no way to get Sent folder of a shared/automapped mailbox. We need to iterate and check for its names. If English is used “Sent Items” is sufficient. For other languages, we need to add translations (function isSentItemsFolder).

Categories
Uncategorized

Pull users from AD

I needed:

  • users from AD with specific OU
  • non disabled
  • filter by department
  • manager details
  • last logon time and other details

For pulling active (non disabled) users belonging to specific group along with their managers name into CSV, I made following powershell script. Output is then loaded into excel and send automatically to managers for approval. Department “x” means a special user which will be omitted.

$FileName="c:\somepath\somefile.txt"

if (Test-Path $FileName) 
{
  Remove-Item $FileName
}

$fileEncoding = "Default"

Out-File -encoding $fileEncoding $FileName

$dn = (Get-ADGroup 'Some group').DistinguishedName
$users = Get-ADUser -Filter " memberof -RecursiveMatch '$dn'" -Properties $properties

Foreach ($User in $Users)
{
 if ($user.Enabled -and ($user.Department -ne "x")) {      
  $userName=$user.UserPrincipalName
  $ou=$user.DistinguishedName.split(',OU=')[5]
  $man=$user.Manager
  $mail=$user.mail
 
  if ($man -ne $null) {	  
	$mgrUsr=(Get-ADUser $man -Properties UserPrincipalName,DisplayName,mail)
	$mngr=$mgrUsr.UserPrincipalName + ";" +$mgrUsr.mail + ";" + $mgrUsr.DisplayName
  } else {
	$mngr=";;"  
  }
  ($user.UserPrincipalName + ";" +  $user.cn + ";" + $user.LastLogonDate + ";" + $ou + ";" + ";" + $mngr  + ";" + $user.Department)  | Out-File -encoding $fileEncoding $FileName -Append 
  
 } 
}

for VPS hosting go here:

Categories
Wordpress WP plugins

CJ feed content generator

This WordPress plugin can import product feeds in Google format which is (used by affiliate platforms like Commission Junction and others) and create whole affiliate website from it with few clicks.

It is really that simple as import a feed and then place shortcode on the frontpage or any other page to become your affiliate site.

Main features

  • import / bulk import even huge feed files
  • automatically generate categories with product counts
  • store products as custom posts+metas or in dedicated table (for lightning fast filtering)
  • internal caching system for even better performance
  • easy templating system for custom appearance
  • ajax powered loading more products (instead of pagination, next items are loaded when you scroll to the bottom like on Facebook)
  • ajax product filtering

Demos

https://www.81gr.com/

Download

you can soon find downloadable plugin on wordpress plugin site, meanwhile, if you are interested, drop a comment below

Categories
Cheats and Scripts Tools

FOE tool

I made a tool for the game Forge of Empires that makes boring clicking for you. Check out the tool on this page:

Categories
Wordpress

Adding plugins to WP repo

Step 1.: create wp dev account at https://developer.wordpress.org/

Step 2.: prepare nice readme.txt, have it checked with https://wordpress.org/plugins/developers/readme-validator/

Step 3.: pack it all together in a zip and submit using https://wordpress.org/plugins/developers/add/

Step 4.: wait for approval

Step 5.: upload using SVN to WP repo. Using Windows you can:

  • download tortoise svn check option to install command line tools
  • create a folder for your files
mkdir my-local-dir
  • download your files with
svn co http://svn.wp-plugins.org/your-plugin-name my-local-dir
  • put your files into trunk folder, then
svn add trunk/*
  • upload files into wp repo
svn ci -m 'my plugin release' --username yourusername --password yourpassword
  • getting error “plugin is not under version control?” So did I. All docs fails for Windows, you need to use double quotes instead of single quotes. so:
svn ci -m "my plugin release" --username yourusername --password yourpassword
  • should do the trick

Enjoy!

Categories
Wordpress WP plugins

WP custom read more image effect block

I have made this simple custom block option to Guttenberg editor with fancy image and a read more link.

Demo:

wp plugin url: https://wordpress.org/plugins/custom-read-more-image-effect-block

Categories
Wordpress

Deleting wordpress posts

Running wp_delete_post($postId,true); for every post could take serious amount of time. If you need to delete everything let’s say from post _id>320 and category equals to some_category, then this is much more faster solution:

(run mysql commands from phpmyadmin or somewhere,

DELETE from wp_posts WHERE ID>320
DELETE from wp_postmeta WHERE post_id>320
DELETE from wp_terms WHERE term_id>1
DELETE from wp_term_relationships WHERE object_id>320
DELETE from wp_term_taxonomy WHERE taxonomy like 'some_category'
Categories
Programming Tools

Anti-ransomware script solution

The idea behind this is simple- if we find out files are being changed quickly, we can still make steps to save much of valuable data from ransomware infection.

That’s why we create a “honeypot” with files likely to be encrypted by ransomware. On windows those have following extensions: doc, docx, jpg, png, xls, xlsx and txt. These files are made with a random content and placed to easily reachable places (meaning not buried deeply in directory structure). Also a ransomware usually goes through the file system structure in alphabetical order, so c:\afile\ would be likely to hit sooner than c:\wrong\dang\files\honeypot\something.

Anyway, now we have the honeypot files, we need to watch over them and as soon as they are changed send alert, disconnect network to prevent further infection or shutdown the computer.

We can solve this completely within a windows batch file with windows utilities involved (certutil.exe for generating md5 hashes and fc.exe for comparing them). A simple task in windows task scheduler runs the .bat in short intervals making the job done.

If you are interested, I am willing to explain more or even sell the code along with documentation.

I have also such application written in C# which runs in background- so no need to use task scheduler- so the emergency action happens immediately when files are enrypted.

Categories
Dynamics NAV / Navision

Dynamics NAV- fieldref

In case we need to import field programatically, without direct referencnig, there is a FieldRef in Navision.


setField(tabName : Text[30];fieldId : Integer;mVal : Text[1024])
IF fieldId < 1 THEN EXIT;
IF tabName = 'sometablename' THEN BEGIN
 greRecRef.GETTABLE(greNS); // get table reference
 greFieldRef:=greRecRef.FIELD(fieldId);
 IF FORMAT(greFieldRef.TYPE) = 'Boolean' THEN BEGIN
   IF (mVal = '1') OR (UPPERCASE(mVal) = 'YES') THEN greFieldRef.VALUE:=TRUE
   ELSE greFieldRef.VALUE:=FALSE;
 END ELSE IF (FORMAT(greFieldRef.TYPE) = 'Integer') OR (FORMAT(greFieldRef.TYPE) = 'Decimal') THEN BEGIN
   EVALUATE(mNum,mVal);
   greFieldRef.VALUE:=mNum;
 END ELSE IF (FORMAT(greFieldRef.TYPE) = 'Code') OR (FORMAT(greFieldRef.TYPE) = 'Text') THEN BEGIN
   greFieldRef.VALUE:=mVal;
 END ELSE IF (FORMAT(greFieldRef.TYPE) = 'Date') THEN BEGIN
   EVALUATE(mDate,mVal);
   greFieldRef.VALUE:=mDate;
 END ELSE IF (FORMAT(greFieldRef.TYPE) = 'Time') THEN BEGIN
   EVALUATE(mTime,mVal);
   greFieldRef.VALUE:=mTime;
 END ELSE ERROR('This field type is not yet covered.');
END;