├── README.md ├── samba └── smb.conf ├── unix ├── .gitignore ├── editremote.py ├── meld.py ├── merger.py ├── of.py ├── requirements.txt ├── tof └── winmerge.py └── windows ├── FolderOpener2 ├── FolderOpener2.ico ├── FolderOpener2.sln └── FolderOpener2 │ ├── .gitignore │ ├── FolderOpener2.csproj │ ├── FolderOpener2.csproj.user │ ├── FolderOpener2.ico │ ├── LineReader.cs │ ├── MainWindow.Designer.cs │ ├── MainWindow.cs │ ├── MainWindow.resx │ ├── Program.cs │ ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ ├── Settings.settings │ └── licenses.licx │ ├── app.config │ └── bin │ └── Release │ ├── FolderOpener2.exe │ ├── FolderOpener2.exe.config │ ├── FolderOpener2.pdb │ ├── FolderOpener2.vshost.exe │ ├── FolderOpener2.vshost.exe.config │ └── FolderOpener2.vshost.exe.manifest └── FolderOpenerGo ├── .gitignore ├── Makefile ├── folderOpener.go └── makeRunCommand.py /README.md: -------------------------------------------------------------------------------- 1 | OpenFile 2 | =========== 3 | **OpenFile** is a set of scripts to close the gap of developing on Linux in a Windows box. 4 | 5 | ##The Problem 6 | 7 | - Unix is an awesome development environment, but the UI is not. 8 | - Windows has a nice UI and works with my hardware but is not good for programming. 9 | - Mac has only the disadvantages above (any many others). 10 | 11 | ##The Objective 12 | 13 | To have Windows on my computer, but with a *real* Unix shell (not cygwin) instead of *cmd.exe*. 14 | 15 | ##The solution 16 | 17 | * Have Windows installed as your main OS 18 | * Install Unix on another machine (or a Virtual Machine ) 19 | * Make sure both machines connect with each other though IP ( NAT or BRIDGE ) 20 | * Share your Unix / folder with Windows thought **samba** ( mine is z: ) 21 | * Use **putty** to connect to your Unix box, authenticating through ssh keys so you *never* have to type any password 22 | * on Windows, run FolderOpener2.exe, which is the server that handles requests from Linux 23 | * on Linux, run of.py and the other python scripts. It's even more fun if you put them on your PATH 24 | * you may want to edit of.py to change the path of the openers. Since spaces don't work well, use *dir /X* to get the 8 chars folder names 25 | 26 | 27 | ##An alternative solution if you use Windows 10 with Microsoft Subsystem for Linux (bash on Ubuntu on Windows) 28 | 29 | * use Windows 10 with "bash on Ubuntu on Windows" 30 | * on Windows, run FolderOpener2.exe, which is the server that handles requests from Linux 31 | * on bash, run of.py and the other python scripts. It's even more fun if you put them on your PATH 32 | * you may want to edit of.py to change the path of the openers. Since spaces don't work well, use *dir /X* to get the 8 chars folder names 33 | 34 | 35 | ##The Script 36 | 37 | 38 | The script is called **of**, which means both *openfile* and *openfolder*. It opens files and folders located in the Unix box on the Windows machine, just like **start.exe** (technical explanation later). It also launches websites from the unix box in the Windows browser 39 | 40 | 41 | Examples: 42 | 43 | If you type (on your Unix box, though putty): 44 | 45 | $pwd 46 | #/home/marcos/folder1/folder2 47 | 48 | $of 49 | #opens Z:\home\marcos\folder1\folder2 on Windows Explorer 50 | 51 | $of anotherfolder 52 | #opens Z:\home\marcos\folder1\folder2\anotherfolder on Windows Explorer 53 | 54 | $of http://google.com 55 | #opens http://google.com on Windows' default internet browser 56 | 57 | $of https://google.com 58 | #opens https://google.com on Windows' default internet browser 59 | 60 | $of .. 61 | #opens Z:\home\marcos\folder1 on Windows Explorer 62 | 63 | $of ../../../../../../../../ 64 | #gives you an error 65 | 66 | $of /tmp 67 | #opens z:/tmp 68 | 69 | $of /tmp/blah.txt 70 | #opens z:\tmp\blah.txt on Windows with the associated editor ( notepad.exe ) 71 | #or microsoft visual studio code if you did your homework properly 72 | 73 | $of myapp/somescript.py 74 | #opens Z:\home\marcos\folder1\folder2\myapp\myscript.py on Windows with the associated editor 75 | 76 | $of myspreadsheet.xlsx 77 | #opens Z:\home\marcos\folder1\folder2\myapp\myspreadsheet.xlsx on Windows with the associated editor (Excel/OpenOffice) 78 | 79 | **bonus** 80 | $of File "/home/marcos/3s/code/.envGama/src/django/django/core/servers/basehttp.py", line 139, in __init__ 81 | #open z:\home\marcos\3s\code\.engGama\src\django\django\core\servers\basehttp.py on line 139 82 | 83 | $of "/home/marcos/3s/code/.envGama/src/django/django/core/servers/basehttp.py", line 139, in __init__ 84 | #open z:\home\marcos\3s\code\.engGama\src\django\django\core\servers\basehttp.py on line 139 85 | 86 | 87 | ## How it works 88 | 89 | It is necessary to run a C# server on Windows which accepts and runs remote commands from the Unix box. 90 | 91 | It is actually not insecure if used properly (yes, it was made to be used by adults). Whenever one runs **of**, it sends the request to the IP which is connected to the virtual terminal (obtained via `who`). The server will receive the request and pop up on the an UI saying that it received a request. If you click on accept, it will start trusting this IP address. 92 | Some basic security features: 93 | 94 | * it only trusts one IP at a time (i.e. trusting another IP will automatically untrust the former IP) 95 | * it does not save the trusted IP anywhere, so if you restart the program it will ask it again. 96 | 97 | 98 | That means the tool is safe as long as you are not running nasty code **AND** you are the only person on the unix box. 99 | 100 | 101 | ## What comes in the package 102 | 103 | * smb.conf 104 | * the `of.py` python script 105 | * the C# server (compiled and source) # no install and no config, just click and run! 106 | * this documentation 107 | 108 | ## Settings 109 | 110 | I recommend uncommenting the following lines on `of` 111 | ALTERNATIVEOPENER="c:\progra~1\sublim~1\sublim~1.exe" 112 | as the default editor is wordpad.exe ( common denonimator ) 113 | Also, you must change your folder paths on `of` ( z: is / as default ) 114 | 115 | 116 | 117 | ## merger 118 | 119 | merger is a tool that uses openfile so one can use winmerge to see diference between branches 120 | 121 | 122 | usage: ./merger.py FIRST_BRANCH SECOND_BRANCH FILE 123 | 124 | opens WinMerge to compare the file from both branches 125 | 126 | 127 | ## Meta 128 | Created by Marcos Diez < marcos AT unitron.com.br > 129 | Released under the MIT License: http://www.opensource.org/licenses/mit-license.php 130 | http://github.com/marcosdiez/openfile 131 | 132 | 133 | Icon by http://www.creativefreedom.co.uk/ ( http://www.iconfinder.com/icondetails/61771/48/folder_icon ) 134 | 135 | -------------------------------------------------------------------------------- /samba/smb.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Sample configuration file for the Samba suite for Debian GNU/Linux. 3 | # 4 | # 5 | # This is the main Samba configuration file. You should read the 6 | # smb.conf(5) manual page in order to understand the options listed 7 | # here. Samba has a huge number of configurable options most of which 8 | # are not shown in this example 9 | # 10 | # Some options that are often worth tuning have been included as 11 | # commented-out examples in this file. 12 | # - When such options are commented with ";", the proposed setting 13 | # differs from the default Samba behaviour 14 | # - When commented with "#", the proposed setting is the default 15 | # behaviour of Samba but the option is considered important 16 | # enough to be mentioned here 17 | # 18 | # NOTE: Whenever you modify this file you should run the command 19 | # "testparm" to check that you have not made any basic syntactic 20 | # errors. 21 | # A well-established practice is to name the original file 22 | # "smb.conf.master" and create the "real" config file with 23 | # testparm -s smb.conf.master >smb.conf 24 | # This minimizes the size of the really used smb.conf file 25 | # which, according to the Samba Team, impacts performance 26 | # However, use this with caution if your smb.conf file contains nested 27 | # "include" statements. See Debian bug #483187 for a case 28 | # where using a master file is not a good idea. 29 | # 30 | 31 | #======================= Global Settings ======================= 32 | 33 | [global] 34 | 35 | ## Browsing/Identification ### 36 | 37 | # Change this to the workgroup/NT-domain name your Samba server will part of 38 | workgroup = WORKGROUP 39 | 40 | # server string is the equivalent of the NT Description field 41 | server string = %h server (Samba, Ubuntu) 42 | 43 | # Windows Internet Name Serving Support Section: 44 | # WINS Support - Tells the NMBD component of Samba to enable its WINS Server 45 | # wins support = no 46 | 47 | # WINS Server - Tells the NMBD components of Samba to be a WINS Client 48 | # Note: Samba can be either a WINS Server, or a WINS Client, but NOT both 49 | ; wins server = w.x.y.z 50 | 51 | # This will prevent nmbd to search for NetBIOS names through DNS. 52 | dns proxy = no 53 | 54 | # What naming service and in what order should we use to resolve host names 55 | # to IP addresses 56 | ; name resolve order = lmhosts host wins bcast 57 | 58 | #### Networking #### 59 | 60 | # The specific set of interfaces / networks to bind to 61 | # This can be either the interface name or an IP address/netmask; 62 | # interface names are normally preferred 63 | ; interfaces = 127.0.0.0/8 eth0 64 | 65 | # Only bind to the named interfaces and/or networks; you must use the 66 | # 'interfaces' option above to use this. 67 | # It is recommended that you enable this feature if your Samba machine is 68 | # not protected by a firewall or is a firewall itself. However, this 69 | # option cannot handle dynamic or non-broadcast interfaces correctly. 70 | ; bind interfaces only = yes 71 | 72 | 73 | 74 | #### Debugging/Accounting #### 75 | 76 | # This tells Samba to use a separate log file for each machine 77 | # that connects 78 | log file = /var/log/samba/log.%m 79 | 80 | # Cap the size of the individual log files (in KiB). 81 | max log size = 1000 82 | 83 | # If you want Samba to only log through syslog then set the following 84 | # parameter to 'yes'. 85 | # syslog only = no 86 | 87 | # We want Samba to log a minimum amount of information to syslog. Everything 88 | # should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log 89 | # through syslog you should set the following parameter to something higher. 90 | syslog = 0 91 | 92 | # Do something sensible when Samba crashes: mail the admin a backtrace 93 | panic action = /usr/share/samba/panic-action %d 94 | 95 | 96 | ####### Authentication ####### 97 | 98 | # "security = user" is always a good idea. This will require a Unix account 99 | # in this server for every user accessing the server. See 100 | # /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html 101 | # in the samba-doc package for details. 102 | # security = user 103 | 104 | # You may wish to use password encryption. See the section on 105 | # 'encrypt passwords' in the smb.conf(5) manpage before enabling. 106 | encrypt passwords = true 107 | 108 | # If you are using encrypted passwords, Samba will need to know what 109 | # password database type you are using. 110 | ; passdb backend = tdbsam 111 | 112 | obey pam restrictions = yes 113 | 114 | # This boolean parameter controls whether Samba attempts to sync the Unix 115 | # password with the SMB password when the encrypted SMB password in the 116 | # passdb is changed. 117 | unix password sync = yes 118 | 119 | # For Unix password sync to work on a Debian GNU/Linux system, the following 120 | # parameters must be set (thanks to Ian Kahan < for 121 | # sending the correct chat script for the passwd program in Debian Sarge). 122 | passwd program = /usr/bin/passwd %u 123 | passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . 124 | 125 | # This boolean controls whether PAM will be used for password changes 126 | # when requested by an SMB client instead of the program listed in 127 | # 'passwd program'. The default is 'no'. 128 | pam password change = yes 129 | 130 | # Allow users who've been granted usershare privileges to create 131 | # public shares, not just authenticated ones 132 | usershare allow guests = yes 133 | allow insecure wide links = yes 134 | follow symlinks = yes 135 | wide links = yes 136 | 137 | 138 | # This option controls how unsuccessful authentication attempts are mapped 139 | # to anonymous connections 140 | map to guest = bad user 141 | 142 | ########## Domains ########### 143 | 144 | # Is this machine able to authenticate users. Both PDC and BDC 145 | # must have this setting enabled. If you are the BDC you must 146 | # change the 'domain master' setting to no 147 | # 148 | ; domain logons = yes 149 | # 150 | # The following setting only takes effect if 'domain logons' is set 151 | # It specifies the location of the user's profile directory 152 | # from the client point of view) 153 | # The following required a [profiles] share to be setup on the 154 | # samba server (see below) 155 | ; logon path = \\%N\profiles\%U 156 | # Another common choice is storing the profile in the user's home directory 157 | # (this is Samba's default) 158 | # logon path = \\%N\%U\profile 159 | 160 | # The following setting only takes effect if 'domain logons' is set 161 | # It specifies the location of a user's home directory (from the client 162 | # point of view) 163 | ; logon drive = H: 164 | # logon home = \\%N\%U 165 | 166 | # The following setting only takes effect if 'domain logons' is set 167 | # It specifies the script to run during logon. The script must be stored 168 | # in the [netlogon] share 169 | # NOTE: Must be store in 'DOS' file format convention 170 | ; logon script = logon.cmd 171 | 172 | # This allows Unix users to be created on the domain controller via the SAMR 173 | # RPC pipe. The example command creates a user account with a disabled Unix 174 | # password; please adapt to your needs 175 | ; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u 176 | 177 | # This allows machine accounts to be created on the domain controller via the 178 | # SAMR RPC pipe. 179 | # The following assumes a "machines" group exists on the system 180 | ; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u 181 | 182 | # This allows Unix groups to be created on the domain controller via the SAMR 183 | # RPC pipe. 184 | ; add group script = /usr/sbin/addgroup --force-badname %g 185 | 186 | ########## Printing ########## 187 | 188 | # If you want to automatically load your printer list rather 189 | # than setting them up individually then you'll need this 190 | # load printers = yes 191 | 192 | # lpr(ng) printing. You may wish to override the location of the 193 | # printcap file 194 | ; printing = bsd 195 | ; printcap name = /etc/printcap 196 | 197 | # CUPS printing. See also the cupsaddsmb(8) manpage in the 198 | # cupsys-client package. 199 | ; printing = cups 200 | ; printcap name = cups 201 | 202 | ############ Misc ############ 203 | 204 | # Using the following line enables you to customise your configuration 205 | # on a per machine basis. The %m gets replaced with the netbios name 206 | # of the machine that is connecting 207 | ; include = /home/samba/etc/smb.conf.%m 208 | 209 | # Most people will find that this option gives better performance. 210 | # See smb.conf(5) and /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/speed.html 211 | # for details 212 | # You may want to add the following on a Linux system: 213 | # SO_RCVBUF=8192 SO_SNDBUF=8192 214 | # socket options = TCP_NODELAY 215 | 216 | # The following parameter is useful only if you have the linpopup package 217 | # installed. The samba maintainer and the linpopup maintainer are 218 | # working to ease installation and configuration of linpopup and samba. 219 | ; message command = /bin/sh -c '/usr/bin/linpopup "%f" "%m" %s; rm %s' & 220 | 221 | # Domain Master specifies Samba to be the Domain Master Browser. If this 222 | # machine will be configured as a BDC (a secondary logon server), you 223 | # must set this to 'no'; otherwise, the default behavior is recommended. 224 | # domain master = auto 225 | 226 | # Some defaults for winbind (make sure you're not using the ranges 227 | # for something else.) 228 | ; idmap uid = 10000-20000 229 | ; idmap gid = 10000-20000 230 | ; template shell = /bin/bash 231 | 232 | # The following was the default behaviour in sarge, 233 | # but samba upstream reverted the default because it might induce 234 | # performance issues in large organizations. 235 | # See Debian bug #368251 for some of the consequences of *not* 236 | # having this setting and smb.conf(5) for details. 237 | ; winbind enum groups = yes 238 | ; winbind enum users = yes 239 | 240 | # Setup usershare options to enable non-root users to share folders 241 | # with the net usershare command. 242 | 243 | # Maximum number of usershare. 0 (default) means that usershare is disabled. 244 | ; usershare max shares = 100 245 | 246 | # Allow users who've been granted usershare privileges to create 247 | # public shares, not just authenticated ones 248 | usershare allow guests = yes 249 | 250 | 251 | # This defines how samba deals with the archive bit on Windows. By disabling it, 252 | # the execute permissions start to work as expected ( on the expense of the archive it 253 | # not working, which I personally don't use 254 | 255 | map archive = no 256 | 257 | #======================= Share Definitions ======================= 258 | 259 | # Un-comment the following (and tweak the other settings below to suit) 260 | # to enable the default home directory shares. This will share each 261 | # user's home director as \\server\username 262 | [homes] 263 | comment = Home Directories 264 | browseable = no 265 | create mask = 0644 266 | directory mask = 0755 267 | 268 | # By default, the home directories are exported read-only. Change the 269 | # next parameter to 'no' if you want to be able to write to them. 270 | read only = no 271 | 272 | # File creation mask is set to 0700 for security reasons. If you want to 273 | # create files with group=rw permissions, set next parameter to 0775. 274 | ; create mask = 0700 275 | 276 | # Directory creation mask is set to 0700 for security reasons. If you want to 277 | # create dirs. with group=rw permissions, set next parameter to 0775. 278 | ; directory mask = 0700 279 | 280 | # By default, \\server\username shares can be connected to by anyone 281 | # with access to the samba server. Un-comment the following parameter 282 | # to make sure that only "username" can connect to \\server\username 283 | # The following parameter makes sure that only "username" can connect 284 | # 285 | # This might need tweaking when using external authentication schemes 286 | valid users = %S 287 | 288 | # Un-comment the following and create the netlogon directory for Domain Logons 289 | # (you need to configure Samba to act as a domain controller too.) 290 | ;[netlogon] 291 | ; comment = Network Logon Service 292 | ; path = /home/samba/netlogon 293 | ; guest ok = yes 294 | ; read only = yes 295 | 296 | # Un-comment the following and create the profiles directory to store 297 | # users profiles (see the "logon path" option above) 298 | # (you need to configure Samba to act as a domain controller too.) 299 | # The path below should be writable by all users so that their 300 | # profile directory may be created the first time they log on 301 | ;[profiles] 302 | ; comment = Users profiles 303 | ; path = /home/samba/profiles 304 | ; guest ok = no 305 | ; browseable = no 306 | ; create mask = 0600 307 | ; directory mask = 0700 308 | 309 | [printers] 310 | comment = All Printers 311 | browseable = no 312 | path = /var/spool/samba 313 | printable = yes 314 | ; guest ok = no 315 | ; read only = yes 316 | create mask = 0700 317 | 318 | # Windows clients look for this share name as a source of downloadable 319 | # printer drivers 320 | [print$] 321 | comment = Printer Drivers 322 | path = /var/lib/samba/printers 323 | ; browseable = yes 324 | ; read only = yes 325 | ; guest ok = no 326 | # Uncomment to allow remote administration of Windows print drivers. 327 | # You may need to replace 'lpadmin' with the name of the group your 328 | # admin users are members of. 329 | # Please note that you also need to set appropriate Unix permissions 330 | # to the drivers directory for these users to have write rights in it 331 | ; write list = root, @lpadmin 332 | 333 | # A sample share for sharing your CD-ROM with others. 334 | ;[cdrom] 335 | ; comment = Samba server's CD-ROM 336 | ; read only = yes 337 | ; locking = no 338 | ; path = /cdrom 339 | ; guest ok = yes 340 | 341 | # The next two parameters show how to auto-mount a CD-ROM when the 342 | # cdrom share is accesed. For this to work /etc/fstab must contain 343 | # an entry like this: 344 | # 345 | # /dev/scd0 /cdrom iso9660 defaults,noauto,ro,user 0 0 346 | # 347 | # The CD-ROM gets unmounted automatically after the connection to the 348 | # 349 | # If you don't want to use auto-mounting/unmounting make sure the CD 350 | # is mounted on /cdrom 351 | # 352 | ; preexec = /bin/mount /cdrom 353 | ; postexec = /bin/umount /cdrom 354 | 355 | [root] 356 | user = mdiez 357 | username = mdiez 358 | path = / 359 | writeable = yes 360 | browseable = yes 361 | guest ok = yes 362 | force user = mdiez 363 | create mask = 0644 364 | directory mask = 0755 365 | 366 | 367 | [marcosX] 368 | user = mdiez 369 | username = mdiez 370 | path = /home/mdiez 371 | writeable = yes 372 | browseable = yes 373 | guest ok = yes 374 | force user = mdiez 375 | create mask = 0644 376 | directory mask = 0755 377 | [tmp] 378 | user = mdiez 379 | username = mdiez 380 | path = /tmp 381 | writeable = yes 382 | browseable = yes 383 | guest ok = yes 384 | force user = mdiez 385 | create mask = 0644 386 | directory mask = 0755 387 | -------------------------------------------------------------------------------- /unix/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | __pycache__/ 3 | of.py.bak 4 | of.pyc 5 | -------------------------------------------------------------------------------- /unix/editremote.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import logging 4 | import tempfile 5 | import os 6 | import os.path 7 | import subprocess 8 | import time 9 | import shutil 10 | 11 | #pip install watchdog 12 | from watchdog.observers import Observer 13 | from watchdog.events import FileSystemEventHandler 14 | 15 | class LocalRemoteFile(FileSystemEventHandler): 16 | def __init__(self, remotefile, ssh_key=None): 17 | self.ssh_key = ssh_key 18 | self.remotefile = remotefile 19 | self.generate_temp_file() 20 | self.copy_remote_file_here() 21 | 22 | def copy_remote_file_here(self): 23 | self.copy_file(self.remotefile, self.localfile) 24 | 25 | def copy_local_file_remote(self): 26 | self.copy_file(self.localfile, self.remotefile) 27 | 28 | def copy_file(self, source_file, target_file): 29 | print("Copying {} to {}".format(source_file, target_file)) 30 | if self.ssh_key: 31 | cmd = ["scp", "-i", self.ssh_key, source_file, target_file] 32 | else: 33 | cmd = ["scp", source_file, target_file] 34 | try: 35 | subprocess.check_output(cmd) 36 | except: 37 | pass 38 | 39 | def generate_temp_file(self): 40 | pos = self.remotefile.find(":") 41 | if pos < 0: 42 | print("error: invalid SSH path [{}]".format(self.remotefile)) 43 | sys.exit(1) 44 | remote_path = self.remotefile[pos+1:] 45 | basepath = os.path.basename(remote_path) 46 | self.tempfolder = tempfile.mkdtemp() 47 | self.localfile = os.path.join(self.tempfolder, basepath) 48 | 49 | def on_modified(self, event): 50 | if event.is_directory: 51 | return 52 | self.copy_local_file_remote() 53 | 54 | def usage(): 55 | print(""" 56 | copies the remote file here, open with an editor, watch for signals and sent it back to it's source every time it's update. 57 | the easiest way to edit remote files locally, even better if they are on the other side of the planet and the latency is annoying. 58 | 59 | usage: {0} login@server:/full/path/of/a/file/you/want/to/edit 60 | usage: {0} -i ~/some_key login@server:/full/path/of/a/file/you/want/to/edit 61 | example: {0} john@myserver.com:/tmp/blah.txt 62 | """.format(sys.argv[0])) 63 | 64 | def doit(): 65 | import sys 66 | import time 67 | import logging 68 | from watchdog.observers import Observer 69 | from watchdog.events import LoggingEventHandler 70 | 71 | if __name__ == "__main__": 72 | logging.basicConfig(level=logging.INFO, 73 | format='%(asctime)s - %(message)s', 74 | datefmt='%Y-%m-%d %H:%M:%S') 75 | path = sys.argv[1] if len(sys.argv) > 1 else '.' 76 | event_handler = MyEventHandler() # LoggingEventHandler() 77 | observer = Observer() 78 | observer.schedule(event_handler, path, recursive=False) 79 | observer.start() 80 | try: 81 | while True: 82 | time.sleep(1) 83 | except KeyboardInterrupt: 84 | observer.stop() 85 | observer.join() 86 | 87 | 88 | def go(target_file, ssh_key=None): 89 | print("Copying file...") 90 | event_handler = LocalRemoteFile(target_file, ssh_key) 91 | observer = Observer() 92 | observer.schedule(event_handler, event_handler.tempfolder, recursive=False) 93 | observer.start() 94 | print("Editing File") 95 | subprocess.check_output(["of", event_handler.localfile]) 96 | print("Waiting For Events...") 97 | try: 98 | while True: 99 | time.sleep(1) 100 | except KeyboardInterrupt: 101 | observer.stop() 102 | observer.join() 103 | print("Erasing Temporary Directory") 104 | shutil.rmtree(event_handler.tempfolder) 105 | print("Done") 106 | 107 | def main(): 108 | args = len(sys.argv) 109 | if args == 2: 110 | target_file = sys.argv[1] 111 | return go(target_file) 112 | if args == 4 and sys.argv[1] == "-i": 113 | ssh_key = sys.argv[2] 114 | target_file = sys.argv[3] 115 | return go(target_file, ssh_key) 116 | return usage() 117 | 118 | 119 | if __name__ == "__main__": 120 | main() 121 | -------------------------------------------------------------------------------- /unix/meld.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import os 4 | import os.path 5 | 6 | import of 7 | 8 | MELD_PATH = """c:\\progra~2\\Meld\\Meld.exe""" 9 | 10 | def usage(): 11 | print "usage: meld.py FIRST_FILE SECOND_FILE THIRD_FILE" 12 | 13 | def expect_file_to_exist(filename): 14 | if not os.path.isfile(filename): 15 | print "error: [{}] does not exist".format(filename) 16 | sys.exit(1) 17 | 18 | def launch_meld(first_file, second_file, third_file): 19 | expect_file_to_exist(first_file) 20 | expect_file_to_exist(second_file) 21 | expect_file_to_exist(third_file) 22 | converted_first_file = of.convert_path(first_file) 23 | converted_second_file = of.convert_path(second_file) 24 | converted_third_file = of.convert_path(third_file) 25 | 26 | final_command = """{} "{}" "{}" "{}" """.format( 27 | MELD_PATH, 28 | converted_first_file, 29 | converted_second_file, 30 | converted_third_file 31 | ) 32 | of.send_socket_cmd(final_command) 33 | 34 | def main(): 35 | #no parameter, we open the current folder 36 | if len(sys.argv) != 4: 37 | usage() 38 | sys.exit(1) 39 | 40 | first_file = sys.argv[1] 41 | second_file = sys.argv[2] 42 | third_file = sys.argv[3] 43 | 44 | launch_meld(first_file, second_file, third_file) 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /unix/merger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import of 3 | import sys 4 | import os.path 5 | import os 6 | import subprocess 7 | 8 | winmerge="c:\progs\WinMerge-2.8.4-exe\WinMergeU.exe" 9 | 10 | def check_parameters(): 11 | if len(sys.argv) < 3: 12 | print "usage: {} FIRST_BRANCH SECOND_BRANCH FILE".format(sys.argv[0]) 13 | sys.exit(0) 14 | 15 | the_file = sys.argv[3] 16 | if not os.path.isfile(the_file): 17 | print "File {} does not exist.".format(the_file) 18 | sys.exit(0) 19 | 20 | def obtin_files(the_file, first_branch, second_branch): 21 | def run_cmd(the_parameters, target_file): 22 | print the_parameters 23 | subprocess.check_output(the_parameters) 24 | the_file = the_parameters[3] 25 | print "renaming [{}] to [{}]".format(the_file, target_file) 26 | os.rename(the_file, target_file) 27 | 28 | os.rename(the_file, the_file + ".tmp") 29 | 30 | mask = "/tmp/{}.{}.{}".format(the_file,"{}",of.get_file_extension(the_file)) 31 | first_file = mask.format(first_branch.replace("/","_")) 32 | second_file = mask.format(second_branch.replace("/","_")) 33 | 34 | run_cmd(["git", "checkout", first_branch , the_file], first_file) 35 | #os.rename(the_file, first_file) 36 | 37 | run_cmd(["git", "checkout", second_branch , the_file], second_file) 38 | #os.rename(the_file, second_file) 39 | 40 | 41 | os.rename(the_file + ".tmp", the_file) 42 | 43 | return first_file , second_file 44 | 45 | def main(): 46 | check_parameters() 47 | the_file = sys.argv[3] 48 | first_branch = sys.argv[1] 49 | second_branch = sys.argv[2] 50 | first_file , second_file= obtin_files(the_file,first_branch,second_branch) 51 | 52 | first_path = of.convert_path(first_file) 53 | second_path = of.convert_path(second_file) 54 | 55 | the_command = "{} {} {}".format(winmerge, first_path, second_path) 56 | of.send_socket_cmd(the_command) 57 | 58 | 59 | if __name__=="__main__": 60 | # import rpdb2; rpdb2.start_embedded_debugger("123") 61 | main() 62 | 63 | -------------------------------------------------------------------------------- /unix/of.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from __future__ import unicode_literals 3 | 4 | import time 5 | import subprocess 6 | import sys 7 | import re 8 | import os 9 | import os.path 10 | import socket 11 | # settings 12 | 13 | TARGET_PORT = 9997 14 | 15 | REPLACE_PATH = [ 16 | ["/mnt/c/", "c:\\"], # microsoft linux 17 | ["/mnt/d/", "d:\\"], # microsoft linux 18 | ["/mnt/e/", "e:\\"], # microsoft linux 19 | ["/mnt/f/", "f:\\"], # microsoft linux 20 | ["/", "z:\\"], 21 | # ["/root/", "%LOCALAPPDATA%\\lxss\\root\\"], # microsoft linux 22 | # ["/", "%LOCALAPPDATA%\\lxss\\rootfs\\"], # microsoft linux 23 | ] 24 | 25 | 26 | 27 | openers = { 28 | "androidstudio": { 29 | "path": """C:\\Users\\Marcos\\AppData\\Local\\Android\\android-studio\\bin\\studio64.exe""", 30 | "open_with_line_number_cmd": "{opener} --line {line_number} \"{file_path}\"", 31 | "open_without_line_number_cmd": "{opener} \"{file_path}\"" 32 | }, 33 | "pycharm": { 34 | "path": """C:\\Progra~2\\JetBrains\\PYCHAR~1.1\\bin\\pycharm.exe""", 35 | "open_with_line_number_cmd": "{opener} {project_folder} --line {line_number} \"{file_path}\"", 36 | "open_without_line_number_cmd": "{opener} {project_folder} \"{file_path}\"" 37 | }, 38 | "vscode": { 39 | "path": """c:\\progra~1\\mifa7f~1\\code.exe""", 40 | "open_with_line_number_cmd": "{opener} -g -r {file_path}:{line_number} ", 41 | "open_without_line_number_cmd": "{opener} -r {file_path}" 42 | }, 43 | "explorer": { 44 | "path": "c:\\windows\\explorer.exe", 45 | "open_with_line_number_cmd": '{opener} {file_path}', 46 | "open_without_line_number_cmd": '{opener} {file_path}', 47 | }, 48 | "audacity": { 49 | "path": "c:\\Progra~2\\Audacity\\audacity.exe", 50 | "open_with_line_number_cmd": '{opener} {file_path}', 51 | "open_without_line_number_cmd": '{opener} {file_path}', 52 | }, 53 | "phpstorm": { 54 | "path": "c:\\progra~1\\jetbrains\\phpsto~1.1\\bin\\phpstorm64.exe", 55 | "open_with_line_number_cmd": "{opener} --line {line_number} {file_path}", 56 | "open_without_line_number_cmd": "{opener} {file_path}", 57 | }, 58 | "notepad++": { 59 | "path": "c:\\progs\\notepadplusplus\\notepad++.exe", 60 | "open_with_line_number_cmd": "{opener} -n{line_number} {file_path}", 61 | "open_without_line_number_cmd": "{opener} {file_path}", 62 | } 63 | } 64 | 65 | open_associations = { 66 | # ".py": openers["pycharm"], 67 | # ".php": openers["phpstorm"], 68 | ".mp3": openers["explorer"], 69 | ".csv": openers["explorer"], 70 | ".xls": openers["explorer"], 71 | ".xlsx": openers["explorer"], 72 | ".doc": openers["explorer"], 73 | ".docx": openers["explorer"], 74 | ".jpg": openers["explorer"], 75 | ".png": openers["explorer"], 76 | ".ico": openers["explorer"], 77 | ".sqlite3": openers["explorer"], 78 | ".pdf": openers["explorer"], 79 | # ".java": openers["androidstudio"], 80 | ".wav": openers["audacity"], 81 | # "*": openers["notepad++"], 82 | "*" : openers["vscode"], 83 | } 84 | 85 | #the ALTERNATIVEOPENER will be used for files without extensions (README, .bashrc, etc...) 86 | #ALTERNATIVEOPENER="wordpad.exe" 87 | #the default opener will use windows associations. I actually use sublime edit for everything. 88 | #DEFAULTOPENER = "" 89 | 90 | 91 | ################################################# 92 | def main(): 93 | #no parameter, we open the current folder 94 | if len(sys.argv) == 1: 95 | open_url(os.getcwd()) 96 | return 97 | 98 | if sys.argv[1] in ( "-h", "--help", "-help" ): 99 | usage() 100 | return 101 | 102 | parse_user_defined_opener() 103 | 104 | if sys.argv[1] == "File" and not os.path.exists("File"): 105 | del sys.argv[1] 106 | 107 | if len(sys.argv) > 2 and sys.argv[2] == "line" and not os.path.exists("line"): 108 | #now this is for python errors, like 109 | 110 | # File "/home/marcos/3s/code/.envGama/src/django/django/core/servers/basehttp.py", line 139, in __init__ 111 | line_number = sys.argv[3].replace(",", "") 112 | the_file = sys.argv[1].replace(",", "") 113 | openfile(the_file, line_number) 114 | return 115 | 116 | first = True 117 | for parameter in sys.argv[1:]: 118 | if first: 119 | first = False 120 | else: 121 | #time.sleep(3) 122 | pass 123 | open_url(parameter) 124 | return 125 | 126 | 127 | def parse_user_defined_opener(): 128 | global USER_DEFINED_OPENER 129 | magic_string = "--opener=" 130 | counter = 0 131 | for argv in sys.argv: 132 | if argv.find(magic_string) == 0: 133 | del sys.argv[counter] 134 | USER_DEFINED_OPENER = argv[len(magic_string):] 135 | return 136 | counter += 1 137 | 138 | 139 | def open_url(target_url): 140 | if is_internet_address(target_url): 141 | send_socket_cmd(target_url) 142 | return 143 | 144 | if os.path.isdir(target_url): 145 | # opendir(target_url) 146 | openfile(target_url, opener=openers["explorer"]) 147 | return 148 | 149 | if os.path.isfile(target_url): 150 | openfile(target_url) 151 | return 152 | 153 | #files that have a column and a number followed by should be interpreted as line numbers 154 | cln = target_url.find(":") 155 | if cln > 0: 156 | file_name = target_url[0:cln] 157 | if os.path.isfile(file_name): 158 | line_number = target_url[cln + 1:] 159 | openfile(file_name, line_number) 160 | return 161 | 162 | target_url = sys.argv[1][0:-1] 163 | if os.path.isfile(target_url): 164 | line_number = sys.argv[3].replace(",", "") 165 | openfile(target_url, line_number) 166 | return 167 | 168 | print("Error: File/Dir [%s] does not exist." % target_url) 169 | 170 | 171 | def is_internet_address(target_url): 172 | return target_url.find("http://") == 0 or target_url.find("https://") == 0 173 | 174 | 175 | def opendir(the_path): 176 | send_socket_cmd(convert_path(the_path)) 177 | 178 | 179 | def convert_path(the_path): 180 | return path_replaced(make_absolute_path_if_necessary(the_path)) 181 | 182 | 183 | def get_file_extension(the_path): 184 | last_dot = the_path.rfind(".") 185 | return the_path[last_dot + 1:].lower() 186 | 187 | 188 | def openfile(the_path, line_number=None, opener=None): 189 | last_dot = the_path.rfind(".") 190 | extension = the_path[last_dot:] 191 | 192 | if opener is None: 193 | if extension in open_associations: 194 | opener = open_associations[extension] 195 | else: 196 | opener = open_associations["*"] 197 | 198 | if line_number is None: 199 | cmd = opener["open_without_line_number_cmd"] 200 | else: 201 | cmd = opener["open_with_line_number_cmd"] 202 | 203 | the_path = make_absolute_path_if_necessary(the_path) 204 | 205 | project_folder = path_replaced(get_project_folder(the_path)) 206 | file_path = path_replaced(the_path) 207 | 208 | the_cmd = cmd.format(opener=opener["path"], 209 | file_path=file_path, 210 | line_number=line_number, 211 | project_folder=project_folder 212 | ) 213 | 214 | send_socket_cmd(the_cmd) 215 | 216 | def get_project_folder(file_path): 217 | # this is ridiculous 218 | # a PyCharm project stays under a .idea folder 219 | # so I have to look for the folder myself in order for pycharm to work as expected 220 | folder = os.path.dirname(file_path) 221 | 222 | while True: 223 | if os.path.isdir(os.path.join(folder, ".idea")): 224 | return folder 225 | 226 | pos = folder.rfind("/") 227 | if pos < 1: 228 | break 229 | folder = folder[0:pos] 230 | 231 | return "" 232 | 233 | 234 | def send_socket_cmd(msg): 235 | 236 | msg = msg.strip().encode() 237 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 238 | sock.connect((server_ip(), TARGET_PORT)) 239 | totalsent = 0 240 | msglen = len(msg) 241 | while totalsent < msglen: 242 | sent = sock.send(msg[totalsent:]) 243 | if sent == 0: 244 | raise RuntimeError("socket connection broken") 245 | totalsent = totalsent + sent 246 | 247 | 248 | def make_absolute_path_if_necessary(the_path): 249 | if the_path[0] != "/": 250 | the_path = os.getcwd() + "/" + the_path 251 | return os.path.realpath(the_path) 252 | 253 | 254 | def path_replaced(the_path): 255 | old_path = the_path 256 | for replace_pair in REPLACE_PATH: 257 | if replace_pair[0] in the_path: 258 | the_path = the_path.replace(replace_pair[0], replace_pair[1], 1) 259 | break 260 | the_path = the_path.replace(os.sep, "\\") 261 | if the_path != "": 262 | print("{} -- {} -> {}".format(server_ip(), old_path, the_path)) 263 | return the_path 264 | 265 | 266 | def is_microsoft_linux(): 267 | with open("/proc/version") as f: 268 | file_content = f.read() 269 | return "Microsoft" in file_content 270 | return False 271 | 272 | 273 | def server_ip(): 274 | if is_microsoft_linux(): 275 | return "127.0.0.1" 276 | #IP=`who --ips -m|egrep -o --color=no "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"` 277 | output = subprocess.check_output(["who", "--ips", "-m"]).decode('ascii') 278 | the_ip = re.search("\\d+\\.\\d+.\\d+.\\d+", output) 279 | return the_ip.group(0) 280 | 281 | 282 | def usage(): 283 | """explains how to use the program""" 284 | 285 | print("""Opens Folders and Files on the remote machine. 286 | usage: 287 | 288 | of /tmp/blah.txt 289 | of somefolder" 290 | of somefolder/otherfolder/blah.xls 291 | of File "/home/marcos/3s/code/.envGama/src/django/django/core/servers/basehttp.py", line 139, in __init__ #open on line 139 292 | of "/home/marcos/3s/code/.envGama/src/django/django/core/servers/basehttp.py", line 139, in __init__ #open on line 139 293 | 294 | """) 295 | 296 | 297 | if __name__ == "__main__": 298 | main() 299 | -------------------------------------------------------------------------------- /unix/requirements.txt: -------------------------------------------------------------------------------- 1 | watchdog==0.8.1 2 | -------------------------------------------------------------------------------- /unix/tof: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | set -e 3 | if [[ ! -z "$1" ]] 4 | then 5 | touch $1 6 | fi 7 | if [[ "$1" == *.sh ]] || [[ "$1" == *.py ]] 8 | then 9 | chmod 755 $1 10 | fi 11 | of $1 12 | -------------------------------------------------------------------------------- /unix/winmerge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import os 4 | import os.path 5 | import hashlib 6 | import of 7 | 8 | WINMERGE_PATH = """c:\\progs\\WinMerge-2.8.4-exe\\WinMergeU.exe""" 9 | MELD_PATH = """c:\\progs\\WinMerge\\WinMergeU.exe""" # """c:\\progra~2\\Meld\\Meld.exe""" 10 | 11 | 12 | def md5(fname): 13 | hash_md5 = hashlib.md5() 14 | with open(fname, "rb") as f: 15 | for chunk in iter(lambda: f.read(4096), b""): 16 | hash_md5.update(chunk) 17 | return hash_md5.hexdigest() 18 | 19 | def usage(): 20 | print("usage: winmerge.py FIRST_FILE SECOND_FILE [THIRD_FILE]") 21 | 22 | def expect_file_to_exist(filename_or_folder): 23 | if os.path.isfile(filename_or_folder) or os.path.isdir(filename_or_folder): 24 | return True 25 | print("error: [{}] does not exist".format(filename_or_folder)) 26 | sys.exit(1) 27 | 28 | def launch_winmerge(first_file, second_file): 29 | expect_file_to_exist(first_file) 30 | expect_file_to_exist(second_file) 31 | converted_first_file = of.convert_path(first_file) 32 | converted_second_file = of.convert_path(second_file) 33 | 34 | final_command = """{} {} {} """.format( 35 | WINMERGE_PATH, converted_first_file, converted_second_file) 36 | of.send_socket_cmd(final_command) 37 | 38 | def launch_meld(first_file, second_file, third_file): 39 | expect_file_to_exist(first_file) 40 | expect_file_to_exist(second_file) 41 | expect_file_to_exist(third_file) 42 | converted_first_file = of.convert_path(first_file) 43 | converted_second_file = of.convert_path(second_file) 44 | converted_third_file = of.convert_path(third_file) 45 | 46 | final_command = """{} {} {} {} """.format( 47 | MELD_PATH, 48 | converted_first_file, 49 | converted_second_file, 50 | converted_third_file 51 | ) 52 | of.send_socket_cmd(final_command) 53 | 54 | def main(): 55 | #no parameter, we open the current folder 56 | num_parameters = len(sys.argv) 57 | if num_parameters == 3: 58 | if not os.path.isdir(sys.argv[1]) and md5(sys.argv[1]) == md5(sys.argv[2]): 59 | print("Error: both files are the same. No point in opening them with WinMerge") 60 | else: 61 | launch_winmerge(sys.argv[1], sys.argv[2]) 62 | elif num_parameters == 4: 63 | if not os.path.isdir(sys.argv[1]) and md5(sys.argv[1]) == md5(sys.argv[2]) and md5(sys.argv[1]) == md5(sys.argv[3]): 64 | print("Error: all files are the same. No point in opening them with WinMerge") 65 | else: 66 | launch_meld(sys.argv[1], sys.argv[2], sys.argv[3]) 67 | else: 68 | usage() 69 | sys.exit(1) 70 | 71 | 72 | if __name__ == "__main__": 73 | main() 74 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcosdiez/openfile/37fe5d073341d9b404ffa3c92c93f91675b127e9/windows/FolderOpener2/FolderOpener2.ico -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FolderOpener2", "FolderOpener2\FolderOpener2.csproj", "{AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/FolderOpener2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AA04139E-DC9F-419C-B9A0-1C5E9FDB5F04} 8 | WinExe 9 | Properties 10 | FolderOpener2 11 | FolderOpener2 12 | v4.0 13 | 512 14 | publish\ 15 | true 16 | Disk 17 | false 18 | Foreground 19 | 7 20 | Days 21 | false 22 | false 23 | true 24 | 0 25 | 1.0.0.%2a 26 | false 27 | false 28 | true 29 | 30 | 31 | 32 | AnyCPU 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | FolderOpener2.ico 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Form 72 | 73 | 74 | MainWindow.cs 75 | 76 | 77 | 78 | 79 | MainWindow.cs 80 | 81 | 82 | 83 | ResXFileCodeGenerator 84 | Resources.Designer.cs 85 | Designer 86 | 87 | 88 | True 89 | Resources.resx 90 | True 91 | 92 | 93 | 94 | PublicSettingsSingleFileGenerator 95 | Settings.Designer.cs 96 | 97 | 98 | True 99 | Settings.settings 100 | True 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | False 109 | Microsoft .NET Framework 4.5 %28x86 and x64%29 110 | true 111 | 112 | 113 | False 114 | .NET Framework 3.5 SP1 Client Profile 115 | false 116 | 117 | 118 | False 119 | .NET Framework 3.5 SP1 120 | false 121 | 122 | 123 | 124 | 131 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/FolderOpener2.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | en-US 11 | false 12 | 13 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/FolderOpener2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcosdiez/openfile/37fe5d073341d9b404ffa3c92c93f91675b127e9/windows/FolderOpener2/FolderOpener2/FolderOpener2.ico -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/LineReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace FolderOpener2 9 | { 10 | public class LineReader : BinaryReader 11 | { 12 | private Encoding _encoding; 13 | private Decoder _decoder; 14 | 15 | const int bufferSize = 1024; 16 | private char[] _LineBuffer = new char[bufferSize]; 17 | 18 | public LineReader(Stream stream, Encoding encoding) 19 | : base(stream, encoding) 20 | { 21 | this._encoding = encoding; 22 | this._decoder = encoding.GetDecoder(); 23 | } 24 | 25 | public string ReadLine() 26 | { 27 | int pos = 0; 28 | 29 | char[] buf = new char[2]; 30 | 31 | StringBuilder stringBuffer = null; 32 | bool lineEndFound = false; 33 | 34 | while (base.Read(buf, 0, 2) > 0) 35 | { 36 | if (buf[1] == '\r') 37 | { 38 | // grab buf[0] 39 | this._LineBuffer[pos++] = buf[0]; 40 | // get the '\n' 41 | char ch = base.ReadChar(); 42 | // Debug.Assert(ch == '\n'); 43 | 44 | lineEndFound = true; 45 | } 46 | else if (buf[0] == '\r' || buf[0] == '\n') 47 | { 48 | lineEndFound = true; 49 | } 50 | else 51 | { 52 | this._LineBuffer[pos] = buf[0]; 53 | this._LineBuffer[pos + 1] = buf[1]; 54 | buf[1] = buf[0] = '\0'; 55 | pos += 2; 56 | 57 | if (pos >= bufferSize) 58 | { 59 | stringBuffer = new StringBuilder(bufferSize + 80); 60 | stringBuffer.Append(this._LineBuffer, 0, bufferSize); 61 | pos = 0; 62 | } 63 | } 64 | 65 | if (lineEndFound) 66 | { 67 | if (stringBuffer == null) 68 | { 69 | if (pos > 0) 70 | return new string(this._LineBuffer, 0, pos); 71 | else 72 | return string.Empty; 73 | } 74 | else 75 | { 76 | if (pos > 0) 77 | stringBuffer.Append(this._LineBuffer, 0, pos); 78 | return stringBuffer.ToString(); 79 | } 80 | } 81 | } 82 | 83 | if (stringBuffer != null) 84 | { 85 | if (pos > 0) 86 | stringBuffer.Append(this._LineBuffer, 0, pos); 87 | return stringBuffer.ToString(); 88 | } 89 | else 90 | { 91 | if (pos > 0) 92 | return new string(this._LineBuffer, 0, pos); 93 | else 94 | return null; 95 | } 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/MainWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FolderOpener2 2 | { 3 | partial class MainWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.components = new System.ComponentModel.Container(); 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); 33 | this.txtStatus = new System.Windows.Forms.TextBox(); 34 | this.myNotifyIcon = new System.Windows.Forms.NotifyIcon(this.components); 35 | this.SuspendLayout(); 36 | this.Visible = false; 37 | this.ShowInTaskbar = false; 38 | // 39 | // txtStatus 40 | // 41 | this.txtStatus.Dock = System.Windows.Forms.DockStyle.Fill; 42 | this.txtStatus.Location = new System.Drawing.Point(0, 0); 43 | this.txtStatus.Multiline = true; 44 | this.txtStatus.Name = "txtStatus"; 45 | this.txtStatus.ScrollBars = System.Windows.Forms.ScrollBars.Both; 46 | this.txtStatus.Size = new System.Drawing.Size(611, 429); 47 | this.txtStatus.TabIndex = 2; 48 | // 49 | // myNotifyIcon 50 | // 51 | this.myNotifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("myNotifyIcon.Icon"))); 52 | this.myNotifyIcon.Text = "Folder Opener"; 53 | this.myNotifyIcon.Visible = true; 54 | this.myNotifyIcon.DoubleClick += new System.EventHandler(this.myNotifyIcon_DoubleClick); 55 | // 56 | // MainWindow 57 | // 58 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 59 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 60 | this.ClientSize = new System.Drawing.Size(611, 429); 61 | this.Controls.Add(this.txtStatus); 62 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 63 | this.Name = "MainWindow"; 64 | this.Text = "Folder Opener"; 65 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainWindow_FormClosed); 66 | this.Resize += new System.EventHandler(this.MainWindow_Resize); 67 | this.ResumeLayout(false); 68 | this.PerformLayout(); 69 | 70 | } 71 | 72 | #endregion 73 | 74 | private System.Windows.Forms.TextBox txtStatus; 75 | private System.Windows.Forms.NotifyIcon myNotifyIcon; 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/MainWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Windows.Forms; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using System.IO; 8 | 9 | namespace FolderOpener2 10 | { 11 | 12 | public partial class MainWindow : Form 13 | { 14 | int port = 9998; 15 | string allowedIp = ""; 16 | 17 | private Socket socket; 18 | private Thread thread; 19 | 20 | private NetworkStream networkStream; 21 | private BinaryWriter binaryWriter; 22 | private LineReader binaryReader; 23 | 24 | public MainWindow() 25 | { 26 | InitializeComponent(); 27 | this.WindowState = FormWindowState.Minimized; 28 | mimimizeMe(); 29 | thread = new Thread(new ThreadStart(RunServer)); 30 | thread.Start(); 31 | } 32 | 33 | public void updInfo(String textLog) 34 | { 35 | if (this.txtStatus.InvokeRequired) 36 | { 37 | txtStatus.Invoke(new MethodInvoker(delegate 38 | { 39 | txtStatus.Text += textLog + "\r\n"; 40 | txtStatus.SelectionStart = txtStatus.Text.Length; 41 | txtStatus.ScrollToCaret(); 42 | txtStatus.Refresh(); 43 | })); 44 | } 45 | else 46 | { 47 | this.txtStatus.Text = textLog; 48 | } 49 | } 50 | 51 | bool isAuthorized(Socket socket) 52 | { 53 | var ip = getIp(socket); 54 | if (ip == allowedIp) 55 | return true; 56 | 57 | var result = MessageBox.Show( 58 | "Would you like to accept incoming connections from " + ip + " ?", 59 | "Folder Opener", MessageBoxButtons.YesNo); 60 | 61 | if (result == DialogResult.Yes) 62 | { 63 | //StatusBarLabel.Text = "Allowed IP: " + ip; 64 | allowedIp = ip; 65 | return true; 66 | } 67 | return false; 68 | } 69 | 70 | string getIp(Socket socket) 71 | { 72 | var connection = socket.RemoteEndPoint.ToString(); 73 | var pos = connection.IndexOf(":"); 74 | if (pos <= 0) 75 | { 76 | return connection; 77 | } 78 | var ip = connection.Substring(0, pos); 79 | return ip; 80 | } 81 | 82 | public void RunServer() 83 | { 84 | TcpListener tcpListener; 85 | try 86 | { 87 | var ipEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port); 88 | tcpListener = new TcpListener(ipEndPoint); 89 | tcpListener.Start(); 90 | 91 | updInfo("We are listening to port " + port); 92 | 93 | while (true) 94 | { 95 | socket = tcpListener.AcceptSocket(); 96 | if (isAuthorized(socket)) 97 | { 98 | (new Thread(new ThreadStart(ProcessConnection))).Start(); 99 | } 100 | else 101 | { 102 | updInfo("Ignored: [" + socket.RemoteEndPoint + "]"); 103 | socket.Close(); 104 | } 105 | 106 | } 107 | } 108 | catch (Exception ex) //Exception ex) 109 | { 110 | MessageBox.Show(ex.Message); 111 | } 112 | finally 113 | { 114 | if (binaryReader != null) 115 | { 116 | binaryReader.Close(); 117 | } 118 | if (binaryWriter != null) 119 | { 120 | binaryWriter.Close(); 121 | } 122 | if (networkStream != null) 123 | { 124 | networkStream.Close(); 125 | } 126 | if (socket != null) 127 | { 128 | socket.Close(); 129 | } 130 | updInfo("Conection Terminated"); 131 | } 132 | } 133 | 134 | void ProcessConnection() 135 | { 136 | networkStream = new NetworkStream(socket); 137 | binaryWriter = new BinaryWriter(networkStream); 138 | binaryReader = new LineReader(networkStream, Encoding.UTF8); 139 | 140 | // updInfo("conexão recebida!"); 141 | // binaryWriter.Write("\nconexão efetuada!"); 142 | 143 | string messageReceived = ""; 144 | do 145 | { 146 | messageReceived = binaryReader.ReadLine(); 147 | if (String.IsNullOrEmpty(messageReceived)) 148 | { 149 | socket.Close(); 150 | } 151 | else 152 | { 153 | var ip = socket.RemoteEndPoint.ToString(); 154 | runRemoteCommand(messageReceived); 155 | updInfo("[" + ip + ": " + messageReceived + "]"); 156 | } 157 | } while (socket.Connected); 158 | } 159 | 160 | void runRemoteCommand(string messageReceived) 161 | { 162 | if (String.IsNullOrEmpty(messageReceived)) 163 | { 164 | return; 165 | } 166 | messageReceived = messageReceived.Trim(); 167 | 168 | ExecuteCommandSync("start " + messageReceived); 169 | } 170 | 171 | void ExecuteCommandSync(object command) 172 | { 173 | updInfo(command.ToString()); 174 | try 175 | { 176 | // create the ProcessStartInfo using "cmd" as the program to be run, 177 | // and "/c " as the parameters. 178 | // Incidentally, /c tells cmd that we want it to execute the command that follows, 179 | // and then exit. 180 | System.Diagnostics.ProcessStartInfo procStartInfo = 181 | new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command); 182 | 183 | // The following commands are needed to redirect the standard output. 184 | // This means that it will be redirected to the Process.StandardOutput StreamReader. 185 | procStartInfo.RedirectStandardOutput = true; 186 | procStartInfo.UseShellExecute = false; 187 | // Do not create the black window. 188 | procStartInfo.CreateNoWindow = true; 189 | // Now we create a process, assign its ProcessStartInfo and start it 190 | System.Diagnostics.Process proc = new System.Diagnostics.Process(); 191 | proc.StartInfo = procStartInfo; 192 | proc.Start(); 193 | // Get the output into a string 194 | string result = proc.StandardOutput.ReadToEnd(); 195 | // Display the command output. 196 | Console.WriteLine(result); 197 | } 198 | catch (Exception) // objException) 199 | { 200 | // Log the exception 201 | } 202 | } 203 | 204 | private void MainWindow_FormClosed(object sender, FormClosedEventArgs e) 205 | { 206 | myNotifyIcon.Visible = false; 207 | Environment.Exit(0); 208 | } 209 | 210 | void mimimizeMe() 211 | { 212 | myNotifyIcon.Visible = true; 213 | this.ShowInTaskbar = false; 214 | this.Hide(); 215 | } 216 | 217 | private void MainWindow_Resize(object sender, EventArgs e) 218 | { 219 | if (FormWindowState.Minimized == this.WindowState) 220 | { 221 | mimimizeMe(); 222 | } 223 | 224 | else if (FormWindowState.Normal == this.WindowState) 225 | { 226 | myNotifyIcon.Visible = false; 227 | this.ShowInTaskbar = true; 228 | } 229 | } 230 | 231 | private void myNotifyIcon_DoubleClick(object sender, EventArgs e) 232 | { 233 | this.Show(); 234 | this.WindowState = FormWindowState.Normal; 235 | } 236 | 237 | } 238 | 239 | } -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using System.Net; 10 | using System.Net.Sockets; 11 | using System.Threading; 12 | 13 | namespace FolderOpener2 14 | { 15 | static class Program 16 | { 17 | /// 18 | /// The main entry point for the application. 19 | /// 20 | [STAThread] 21 | static void Main() 22 | { 23 | Application.EnableVisualStyles(); 24 | Application.SetCompatibleTextRenderingDefault(false); 25 | Application.Run(new MainWindow()); 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FolderOpener2")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Marcos Diez")] 12 | [assembly: AssemblyProduct("FolderOpener2")] 13 | [assembly: AssemblyCopyright("Copyright Marcos Diez")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5b7d54b2-c46f-4d67-b1aa-045b45c22a01")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.*")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18034 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FolderOpener2.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FolderOpener2.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18034 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FolderOpener2.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/Properties/licenses.licx: -------------------------------------------------------------------------------- 1 | DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v10.1, Version=10.1.12.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a 2 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcosdiez/openfile/37fe5d073341d9b404ffa3c92c93f91675b127e9/windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.exe -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.exe.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcosdiez/openfile/37fe5d073341d9b404ffa3c92c93f91675b127e9/windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.pdb -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.vshost.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcosdiez/openfile/37fe5d073341d9b404ffa3c92c93f91675b127e9/windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.vshost.exe -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.vshost.exe.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /windows/FolderOpener2/FolderOpener2/bin/Release/FolderOpener2.vshost.exe.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /windows/FolderOpenerGo/.gitignore: -------------------------------------------------------------------------------- 1 | folderOpener 2 | folderOpener.exe 3 | -------------------------------------------------------------------------------- /windows/FolderOpenerGo/Makefile: -------------------------------------------------------------------------------- 1 | BINARY_NAME=folderOpener 2 | SOURCE_FILES=folderOpener.go 3 | 4 | all: ${BINARY_NAME} 5 | 6 | 7 | ${BINARY_NAME}: ${SOURCE_FILES} 8 | go fmt ${SOURCE_FILES} 9 | go build -o ${BINARY_NAME} ${SOURCE_FILES} 10 | 11 | ${BINARY_NAME}.exe: ${SOURCE_FILES} 12 | GOOS=windows go build -o ${BINARY_NAME}.exe ${SOURCE_FILES} 13 | 14 | build: ${BINARY_NAME} ${BINARY_NAME}.exe 15 | # echo "xpto" 16 | # go build -o ${BINARY_NAME} ${SOURCE_FILES} 17 | 18 | run: ${BINARY_NAME} 19 | ./${BINARY_NAME} 20 | 21 | clean: 22 | go clean 23 | rm -f ${BINARY_NAME} ${BINARY_NAME}.exe 24 | -------------------------------------------------------------------------------- /windows/FolderOpenerGo/folderOpener.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | ) 10 | 11 | const ( 12 | CONN_HOST = "0.0.0.0" 13 | CONN_PORT = "9997" 14 | CONN_TYPE = "tcp" 15 | ) 16 | 17 | func main() { 18 | if len(os.Args) != 2 { 19 | fmt.Println("Usage: ", os.Args[0], "SOURCE_IP_PREFIX") 20 | os.Exit(1) 21 | } 22 | fmt.Println("Source IP prefix:", os.Args[1]) 23 | // Listen for incoming connections. 24 | l, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT) 25 | if err != nil { 26 | fmt.Println("Error listening:", err.Error()) 27 | os.Exit(1) 28 | } 29 | // Close the listener when the application closes. 30 | defer l.Close() 31 | fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT) 32 | for { 33 | // Listen for an incoming connection. 34 | conn, err := l.Accept() 35 | if err != nil { 36 | fmt.Println("Error accepting: ", err.Error()) 37 | os.Exit(1) 38 | } 39 | // Handle connections in a new goroutine. 40 | go handleRequest(conn) 41 | } 42 | } 43 | 44 | func sanityzeString(inputString string) string { 45 | newString := strings.Replace(inputString, "\n", "", -1) 46 | newString = strings.Replace(newString, "\r", "", -1) 47 | newString = strings.Trim(newString, " ") 48 | 49 | for { 50 | if !strings.Contains(newString, " ") { 51 | break 52 | } 53 | newString = strings.Replace(newString, " ", " ", -1) 54 | } 55 | 56 | return newString 57 | } 58 | 59 | func execHelper(cmd_string string) *exec.Cmd { 60 | cmd_array := strings.Split(cmd_string, " ") 61 | cmd_array_len := len(cmd_array) 62 | 63 | if cmd_array_len == 1 { 64 | return exec.Command(cmd_array[0]) 65 | } 66 | 67 | if cmd_array_len == 2 { 68 | return exec.Command(cmd_array[0], cmd_array[1]) 69 | } 70 | 71 | if cmd_array_len == 3 { 72 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2]) 73 | } 74 | 75 | if cmd_array_len == 4 { 76 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3]) 77 | } 78 | 79 | if cmd_array_len == 5 { 80 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4]) 81 | } 82 | 83 | if cmd_array_len == 6 { 84 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5]) 85 | } 86 | 87 | if cmd_array_len == 7 { 88 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6]) 89 | } 90 | 91 | if cmd_array_len == 8 { 92 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7]) 93 | } 94 | 95 | if cmd_array_len == 9 { 96 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8]) 97 | } 98 | 99 | if cmd_array_len == 10 { 100 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9]) 101 | } 102 | 103 | if cmd_array_len == 11 { 104 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10]) 105 | } 106 | 107 | if cmd_array_len == 12 { 108 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11]) 109 | } 110 | 111 | if cmd_array_len == 13 { 112 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12]) 113 | } 114 | 115 | if cmd_array_len == 14 { 116 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13]) 117 | } 118 | 119 | if cmd_array_len == 15 { 120 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14]) 121 | } 122 | 123 | if cmd_array_len == 16 { 124 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15]) 125 | } 126 | 127 | if cmd_array_len == 17 { 128 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16]) 129 | } 130 | 131 | if cmd_array_len == 18 { 132 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17]) 133 | } 134 | 135 | if cmd_array_len == 19 { 136 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18]) 137 | } 138 | 139 | if cmd_array_len == 20 { 140 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19]) 141 | } 142 | 143 | if cmd_array_len == 21 { 144 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20]) 145 | } 146 | 147 | if cmd_array_len == 22 { 148 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21]) 149 | } 150 | 151 | if cmd_array_len == 23 { 152 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22]) 153 | } 154 | 155 | if cmd_array_len == 24 { 156 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23]) 157 | } 158 | 159 | if cmd_array_len == 25 { 160 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24]) 161 | } 162 | 163 | if cmd_array_len == 26 { 164 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24], cmd_array[25]) 165 | } 166 | 167 | if cmd_array_len == 27 { 168 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24], cmd_array[25], cmd_array[26]) 169 | } 170 | 171 | if cmd_array_len == 28 { 172 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24], cmd_array[25], cmd_array[26], cmd_array[27]) 173 | } 174 | 175 | if cmd_array_len == 29 { 176 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24], cmd_array[25], cmd_array[26], cmd_array[27], cmd_array[28]) 177 | } 178 | 179 | return exec.Command(cmd_array[0], cmd_array[1], cmd_array[2], cmd_array[3], cmd_array[4], cmd_array[5], cmd_array[6], cmd_array[7], cmd_array[8], cmd_array[9], cmd_array[10], cmd_array[11], cmd_array[12], cmd_array[13], cmd_array[14], cmd_array[15], cmd_array[16], cmd_array[17], cmd_array[18], cmd_array[19], cmd_array[20], cmd_array[21], cmd_array[22], cmd_array[23], cmd_array[24], cmd_array[25], cmd_array[26], cmd_array[27], cmd_array[28], cmd_array[29]) 180 | 181 | } 182 | 183 | func runCommand(source_ip string, cmd_string string) { 184 | 185 | if len(cmd_string) == 0 { 186 | return 187 | } 188 | 189 | fmt.Println(fmt.Sprintf("->[%s]->[%s]", source_ip, cmd_string)) 190 | 191 | cmd := execHelper(cmd_string) 192 | stdout, err := cmd.Output() 193 | 194 | if err != nil { 195 | fmt.Println(err.Error()) 196 | return 197 | } 198 | 199 | // // Print the output 200 | // fmt.Println(string(stdout)) 201 | 202 | // if err := cmd.Run(); err != nil { 203 | // log.Fatal(err) 204 | // } 205 | 206 | fmt.Println(fmt.Sprintf("<-[%s]", sanityzeString(string(stdout)))) 207 | } 208 | 209 | // Handles incoming requests. 210 | func handleRequest(conn net.Conn) { 211 | if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok { 212 | source_ip := addr.IP.String() 213 | 214 | if strings.HasPrefix(source_ip, os.Args[1]) { 215 | // Make a buffer to hold incoming data. 216 | buf := make([]byte, 10240) 217 | // Read the incoming connection into the buffer. 218 | reqLen, err := conn.Read(buf) 219 | if err != nil { 220 | fmt.Println("Error reading ", reqLen, " bytes: ", err.Error()) 221 | } 222 | // Send a response back to person contacting us. 223 | conn.Write([]byte("Message received.\n")) 224 | // fmt.Println("[", buf, "]") 225 | 226 | cmd_string := sanityzeString(string(buf[:reqLen])) 227 | 228 | runCommandIfSafe(source_ip, cmd_string) 229 | 230 | } else { 231 | fmt.Println("Ignoring request from non whitelisted IP [", source_ip, "]") 232 | } 233 | } 234 | conn.Close() 235 | } 236 | 237 | func runCommandIfSafe(source_ip string, cmd_string string) { 238 | unsafeCommands := []string{"rm ", "cmd ", "echo ", "del ", "GET ", "POST ", "HEAD ", "PUT ", "OPTIONS ", "PATCH "} 239 | unsafeChars := []string{">", "<", "=", "|", ";"} 240 | 241 | for _, unsafeCommand := range unsafeCommands { 242 | if strings.HasPrefix(cmd_string, unsafeCommand) { 243 | fmt.Println("Ignoring dangerous command [", cmd_string, "]") 244 | return 245 | } 246 | } 247 | 248 | for _, unsafeChar := range unsafeChars { 249 | if strings.Contains(cmd_string, unsafeChar) { 250 | fmt.Println("Ignoring dangerous command [", cmd_string, "]") 251 | return 252 | } 253 | } 254 | runCommand(source_ip, cmd_string) 255 | } 256 | -------------------------------------------------------------------------------- /windows/FolderOpenerGo/makeRunCommand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | LIMIT=3 4 | 5 | for i in range(1, LIMIT+1): 6 | if i != LIMIT: 7 | print(" if cmd_array_len == " + f"{i}" + " {") 8 | 9 | print(" return exec.Command(", end="") 10 | for j in range(0, i): 11 | print(f"cmd_array[{j}]", end="") 12 | if j == i -1 : 13 | print(")") 14 | else: 15 | print(", ", end="") 16 | 17 | 18 | # print("") 19 | if i != LIMIT: 20 | print(" }") 21 | 22 | print("") 23 | --------------------------------------------------------------------------------