Code covered by the BSD License  

Highlights from
pass_protect

from pass_protect by Matt Fig
Creates a password protected pcode version of an M-file.

pass_protect(fname,newfname,pswrd,savemfile)
function [] = pass_protect(fname,newfname,pswrd,savemfile)
%pass_protect(fname,newfname,pswrd,savemfile) password protected pcode.
% This function will create a password protected pcode version of a
% function M-file.  The arguments are as follows:
%
% fname:  The name of the function M-file to encode and protect (a string).
% newfname: The name of the password protected pcode file (a string).
% pswrd:  The password needed to run the pcode the first time (a string).
% savemfile:  Allows the user to save the intermediate M-file ({0} or 1).
%
% This program works by creating a copy of the supplied function, fname, 
% with a password prompt inserted after the help.  Then the copy is 
% converted into pcode for secure distribution.  The user has the option 
% of saving the intermediate M-file, or letting it be deleted after pcode 
% generation.  The default is for the intermediate M-file to be deleted.  
% The original M-file will not be altered.
%
% Example:
% Say you have a function M-file named myfun.m in the current directory.  
% To create a password protected pcode version of myfun.m named pr_myfun.p
% use the following:
% 
% pass_protect('myfun','pr_myfun','Master&Servant',1)
%
% The intermediate M-file, pr_myfun.m, is saved in this example.  In order 
% to use pr_myfun.p, the user will need to enter the password after the  
% function is called the first time.  The user will not have to enter the   
% password for subsequent function calls until a 'clear all' is issued.  
% Also note that there is no need to include the file extention for 
% either of the first two arguments.
%
% Calling pass_protect with no arguments runs a documented example using
% the Matlab function M-file logm.m. Again, logm.m will not be altered.
%
% This function only works on function M-files that do not use nested
% functions.  It is easily modified to work with such functions, perhaps if
% this is often needed I would make another copy of this for that purpose.
% If you are unsure as to how to do this, email me and I will tell you. 
% Hint: you need to add 5 'end's and a -1 to this code.
% Will not work for scripts either.  Works on itself, but with warnings!
%
% See also: pcode

% Created by Matt Fig
% Email: popkenai@yahoo.com
% Built with 2006a on 10-29-2007

if nargin==0  % User wants an example.
    fprintf('\n\t\t%s\n',...
            'Running: pass_protect(''logm'',''pr_logm'',''pass'',1)')
    fprintf('\t\t%s\n','File to be password protected:  logm.m') 
    fprintf('\t\t%s\n','Protected version of logm: pr_logm.p')
    fprintf('\t\t%s\n','Password for use of pr_logm:  pass')
    fprintf('\t\t%s\n','Intermediate M-file saved:  yes')
    fname = 'logm';
    newfname = 'pr_logm';
    pswrd = 'pass';
    savemfile = 1;  % Save the intermediate M-file. 
    fprintf('\t\t%s\n\n',...
            'Now enter this at the command line: pr_logm([3,4;5,60])')
elseif nargin <3
    error('Three or zero inputs are required, see help.  Aborting.');
elseif nargin <4
    savemfile = 0;  % Default to delete the intermediate M-file.
end

if ~ischar(fname) || ~ischar(newfname) || ~ischar(pswrd) % Ignored help?
    error('The first three arguments must by strings.  See help.')
end

insstr{1} = 'persistent pswrdcmp;';  %  These lines prompt for password.
insstr{2} = 'if ~ischar(pswrdcmp)';
insstr{3} = 'pswrdcmp = passprompt;';  % Prompt user for password.
insstr{4} = 'end';
insstr{5} = ['pswrd = ',char(39),pswrd,char(39),';']; % Make a string?
insstr{6} = 'if strcmp(pswrd,pswrdcmp)';  % Check with stored password.
insstr{7} = 'else';
insstr{8} = 'clear pswrdcmp;';  % Let them try again!
insstr{9} = 'error(''Access denied, incorrect password entered.'')';  
insstr{10} = 'end';
insstr{11} = 'clear global rEaLlY_wEiRd_NaMe_PASSword;'; % Get rid of this!

if strfind(fname,'.m'),else fname = [fname, '.m'];end % Check for file ext.
[idxfile,txtfile] = reader(fname,0);  %  Get the indexes for writing.
if strfind(newfname,'.m'),else newfname = [newfname, '.m'];end %  
fl = fopen(newfname,'w+t');  % Open the new file for writting.

for ii = 1:idxfile
    fwrite(fl,sprintf('%s',txtfile{ii}));  % Copy file through the help.
end

fwrite(fl,sprintf('\n%s','  ')); % Write in a buffer blank line.

for ii = 1:11
    fwrite(fl,sprintf('\n%s',insstr{ii}));  % Write in the prompt lines.
end

for ii = idxfile+1:length(txtfile)
    fwrite(fl,sprintf('%s',txtfile{ii})); %  Copy the rest of the file.
end

[idxself,txtself] = reader('pass_protect.m',1);  % Find the password gui.
fwrite(fl,sprintf('\n%s','  '));  % Write in a buffer blank line.

for ii = idxself:length(txtself)
    fwrite(fl,sprintf('%s',txtself{ii}));  % Write in the password gui.
end

fclose(fl);  % Close the new M-file.
pcode(newfname);  % Turn it into pcode.
if savemfile~=1
    delete(newfname);  %  Delete the new M-file unless user entered 1.
end

%------------------------------------------------------------------------
%------------------------------------------------------------------------
function [idx,C] = reader(fname,flag)
% reads an M-file and decides where to put the password prompts.  The
% password prompt will be put after the help in the original file, even
% though the help will be unavailable in the pcode.  This simply serves to
% preserve the standard in case the user wants to keep and inspect the
% M-file.

A = fopen(fname);  % Open the file to be read/copied.
B = fscanf(A,'%c');  % Read the contents into a character array.
fclose(A);  % Close the file.
B = int8(B);  %  Look at the ascii map.
B(B==10)=[];  % Look for linefeeds, delete them.
idx = find(B==13);  % Find returns, used to create a cell array.
idx = [1, idx];
lngth = length(idx);
C = cell(1,lngth);  % Preallocation.

for ii = 1:lngth-1
    C{ii} = char(B(idx(ii):idx(ii+1)-1)); % Put each line into a cell.
end
C{lngth} = char(B(idx(lngth):end));  % Put the last line in a cell.

idxfunc = 1;   idxhlp = 1;

if flag==0
    try  %  The file may not have help, so skip this.
        hlp = sscanf(help(fname),'%c');
        hlp = int8(hlp);
        idx = find(hlp==10);% Here we need to use the linefeeds as index.
        idx = [1, idx];
        lngth = length(idx);
        hlpcell = cell(1,lngth-1);
        for ii = 1:lngth-1
            hlpcell{ii} = char(hlp(idx(ii):idx(ii+1)-1)); % As above.
        end
        idxhlp = find(~cellfun(@isempty,strfind(C,hlpcell{end}(3:end))),...
                      1,'first');  % The last line of the help.
        % Or the line right after the func declaration:          
        idxfunc = find(~cellfun(@isempty,strfind(C,'function')),1,'first');
    catch
        idxfunc = find(~cellfun(@isempty,strfind(C,'function')),1,'first');        
    end

    if idxhlp <= idxfunc % Either insert after help or func decl.
        idx = idxfunc;
    else
        idx = idxhlp;
    end
else  % Here we are looking at THIS file.
    idx = find(~cellfun(@isempty,strfind(C,'function [rEaLlY')),2);
    idx = idx(2);  % Find the line number of passprompt func below.
end

%-------------------------------------------------------------------------
%-------------------------------------------------------------------------
function [rEaLlY_wEiRd_NaMe_PASSword] = passprompt()  %#ok
% This function will be written into the the new M-file to prompt the user 
% for a password.  The global variable is only active until the user closes
% the password prompt dialog, then it is deleted: See line 81 above.
global rEaLlY_wEiRd_NaMe_PASSword  %#ok  Password temporarily stored here.

h_fig = figure('units','pixels','position',[450 450 300 60],...
               'menubar','none','name','Verify Password.'...
               ,'resize','off','NumberTitle','off');
txt1 = uicontrol(h_fig,'style','text','position',[5 20 80 20],...
                 'string','Password:','fontweight','bold',...
                 'HorizontalAlign','left','FontSize',11); %#ok
edt1 = uicontrol(h_fig,'style','edit','position',[90 20 200 20],...
                 'backgroundcolor','w','callback',...
                 @closeit,'tooltipstring',[' Enter your password '...
                 'here.'],'HorizontalAlign','left','KeyPressFcn',...
                 @keypress);          
uicontrol(edt1)  % Put a blinking cursor in edit box.
uiwait  % Suspend other exection until return is pressed.

function [] = closeit(hand,eventdata)  %#ok
% Closes the dialog when user presses return. 
global rEaLlY_wEiRd_NaMe_PASSword  % Pick a name unlikely to be in use.
rEaLlY_wEiRd_NaMe_PASSword = get(gcf,'UserData');  % Retrieve password.
close(gcf)   %

function [] = keypress(hand,eventdata)  %#ok
% Deals with user input.
str1 = get(gcf,'CurrentCharacter');  % The character user entered.
num = int8(str1);
if num == 13  % This is a carriage return.
    return
end
prnt = get(hand,'parent');  % Handle to gui.
str2 = get(hand,'string');  % the string of the edit box.
if num == 8  % Backspace pressed, update password and screen.
    set(hand,'string',str2(1:end-1));
    str3 = get(prnt,'UserData');
    set(prnt,'UserData',str3(1:end-1));
elseif ~isempty(num)
    set(hand,'string',[str2,'*'])  ;  % Print out an asterik in gui.
    set(prnt,'UserData',[get(prnt,'UserData'),str1]); % Update password.
end

Contact us at files@mathworks.com