728x90

킴스큐에서 제공하는 함수를 일반 PHP에서도 활용할 수 있게 수정해서 적용해봤는데 잘 된다.

DB 업데이트할 때에는 로직을 어떻게 적용할 것인지에 따라 유연성있게 적용할 수 있다.

함수화를 잘 해두면 코딩이 편리해진다.

where 조건절은 있을 수도 있고 없을 수도 있다. 이걸 감안해서 만들어져 있다고 보면 된다.

조인의 개념도 알고 보면 아주 쉬운 거다. 역시 이 함수에서 조인한 것을 적용해 볼 수 있다.


function getExt($filename)
{
    $ext = substr(strrchr($filename,"."),1);
    $ext = strtolower($ext);
    return $ext;
}

// DB Query Cutom 함수
function getDbData($table,$where,$data)
{
    global $db;
    $result = mysql_query('select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):''));
    $row = mysql_fetch_array($result);
    return $row;
}

//DB삽입
function getDbInsert($table,$key,$val)
{
    global $db;
    mysql_query("insert into ".$table." (".$key.")values(".$val.")");
}

//DB업데이트
function getDbUpdate($table,$set,$where)
{
    global $db;
    mysql_query('set names utf8');
    mysql_query('set sql_mode=\'\'');
    mysql_query("update ".$table." set ".$set.($where?' where '.getSqlFilter($where):''));
}

//SQL필터링
function getSqlFilter($sql)
{
    return $sql;
}

728x90

'Web 프로그램 > PHP 응용 및 활용' 카테고리의 다른 글

접속 허용 IP 체크  (0) 2016.05.04
문자열 숫자 표기  (0) 2016.04.23
[PHP] 날짜 함수 정리  (0) 2015.08.03
[PHP] 설문조사 종료날짜 체크  (0) 2015.05.27
[PHP] 쿠키와 세션, 그리고 보안  (0) 2015.05.27
블로그 이미지

Link2Me

,
728x90

상위화면 새로 고침을 적어둔다.

<script type="text/javascript">

top.window.location.reload(true);

</script>


새창이 열린 상태에서 부모창을 reload 하고 자신의 창을 닫을 때

<script type="text/javascript"> 
<!-- 
window.opener.parent.location.reload(); // 부모창 새로고침 
window.self.close(); // 현재 팝업 닫기
//--> 
</script>


window.opener는 자식창을 열어준 창을 가리킨다. 

window 를 생략하면 브라우저 특성을 탈 수 있다. 그러므로 반드시 window 를 붙여주는게 좋다.

개발자들이 익스플로러에서만 테스트하면서 window를 생략하는 경우가 있다.


자기자신의 창을 reload 할 경우에는

<script type="text/javascript"> 
<!-- 
location.reload(true);  // 페이지 새로 고침시 서버에서 불러옴 
//--> 
</script>

를 쓰면 될 거 같지만 이 경우에는 if 문을 잘 사용해야 된다.

잘못하면 화면을 계속 reload 하게 될 수 있다.




728x90
블로그 이미지

Link2Me

,
728x90

echo '<script type="text/javascript">alert("파일을 찾을 수가 없습니다!");</script>';


echo '<script type="text/javascript">alert("txt 파일만 등록할 수 있습니다.");</script>';


이렇게 값을 직접 적는 것은 쉽게 해결했는데 값을 받아서 넣는 것에서 원하는 결과가 나오지 않는다.

기본기 부족으로 소소한 곳에서 헤메는 것을 방지하기 위해 기록해둔다.


$msg = '신규'.number_format($newcount).'건, 갱신'.number_format($upcount).'건, 총'.number_format($total_line).'건 등록되었습니다.';


echo "<script type=\"text/javascript\">alert('$msg');</script>";


echo "<script type=\"text/javascript\">alert(\"$msg\");history.go(-1);</script>";


참고로 PHP 가 얼마나 애를 먹이는 언어인지 참고하면 좋을 거 같아서 링크를 걸어둔다.

http://noraesae.github.io/PHP-a-fractal-of-bad-design-kr/

728x90
블로그 이미지

Link2Me

,
728x90

PHP 보안은 PHP 버전에 따른 보안과 Web Application 보안으로 나눌 수 있다.

PHP 5.4 에서는 HTTP header injection 취약점을 개선시켰다.

높은 버전의 PHP 를 사용하는 것이 바람직하지만, 이전버전과의 호환성에 문제가 있을 수 있으므로 Web application 코드를 충분히 테스트하는 것이 좋다.

 

PHP는 사용자의 입력 실수(문자형, 숫자형)를 자동으로 형변환해주는 기능이 있다. 이 기능을 잘못 사용하면 보안에 취약해질 수 있다. 문자열을 비교하고 싶으면 일치 연산자(===)로 비교하거나, 반드시 strcmp()함수를 사용해야 한다.

 

 

PHP 환경설정 파일 중에서 간단하게 정리해둔다.

 

disable_functions = phpinfo()
; phpinfo() 함수는 시스템내의 php,http,mysql 과 관련한 모든 정보를 보여주므로 운용시 막는 것이 좋다.

 

error_reporting  =  E_ALL

; 해킹의 먹이감이 되므로 평소에는 Off 로 해둔다. 에러가 있을 경우 디버깅 가능하도록 에러 메세지를 출력해준다.
display_errors = Off
; 평소에는 해제(Off)한다. 개발환경에서는 디버깅 가능하도록 On하면 에러 메세지를 출력해준다.
display_startup_errors = Off

 

;default 8M 로 되어 있음, upload_max_filesize 보다 크게 설정해야 함

post_max_size = 20M

memory_limit = 128M
upload_max_filesize = 18M

 

allow_url_fopen = Off

; On 인 경우 외부의 URL 을 로컬 파일과 똑같이 취급할 수 있다.

;해당 옵션을 On으로 설정하면 파일 액세스 시 외부 사이트의 파일을 호출할 수 있다.
;특히 include(), require()계열의 함수 사용 시 심각한 보안상의 문제를 유발하게 되므로 반드시 Off로 사용한다.
; PHP injection 공격 방지 목적으로 off 로 설정

; PHP 5.2 이후부터는 allow_url_include = off 로 설정이 분리되었다.

 

date.timezone ="Asia/Seoul"

session.save_path = "/path/to your folder"

; 세션파일을 저장할 폴더를 지정한다.

; UNIX OS에서 기본값은 /tmp 이므로 공유 서버의 경우 다른 사용자가 세션 정보를 읽거나

; 세션 하이젝을 할 수 있으므로 Application 별로 다른 사용자가 액세스할 수 없는 비공개 폴더를 지정하는 것이 좋다.

;session.save_path = /tmp/session 디렉토리를
;chown nobody.nobody /tmp/session
;chmod 750 /tmp/session 이렇게 해주면 된다.

expose_php = Off
;웹서버 헤더에서 PHP 버전 정보 숨기기

session.use_only_cookies = 1
;세션에 대해 쿠키를 사용하고, GET 파라미터로서 세션 ID가 패싱되는 걸 허용하지 않는다.

 

;session.cookie_secure = 1
;SSL 인증서를 설치하고 https 만 사용하는 것이 평문으로 세션 ID가 전송되는 걸 막을 수 있으며, 세션 공격을 더욱 어렵게 만든다.

 

session.cookie_httponly = 1
; 1로 설정하면, 자바스크립트 같은 클라이언트 사이드 스크립트에 노출되지 않게 된다.

session.use_trans_sid = 0
; 세션이 URL이나 Form 의 INPUT으로 의도하지 않게 PHPSESSIONID 가 전송될 경우 방지.  1 설정은 전송됨

기본 설정값

session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440 // 움직임이 없을 경우 세션 유지 시간, default 24분

세션을 10분 동안 유지하기
session.gc_probability = 1
session.gc_divisor = 1
;이값이 100이면 1/100 즉 1%의 확률로 가비지콜렉션이 실행된다.

session.gc_maxlifetime = 600

;사용자가 아무짓 안할 경우 600초 즉 10분 후에 가비지로 보이는 것을 삭제한다.

;지정된 session.save_path 폴더 아래로 가서 변경이 없는 파일을 찾아 지운다.

 

; 보안상 0 으로 놓은 것이 좋다고는 하는데, 세션은 생성되는데 다른 파일에서는 인식이 안된다.
session.auto_start = 1

PHP 설정에서 에러 표시가 Disable 되어 표시 되지 않을때 특정 페이지에서만 에러를 볼 수 있는 방법이다.
ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);

 

=========================================================

session_start();
if($_SESSION['authID']!=1){
    echo "<script>window.top.location.replace('/index.php');</script>";
    exit;
}
를 해주는데 세션이 먹지 않는다.

삽질을 열심히 하면서 알아낸 것은 PHP 파일 인코딩 모드가 UTF8 이면 정상인데 UTF8+BOM 으로 하면 에러가 발생한다.

세션의 경우에도 characterset 을 맞춰줘야 정상동작한다.

 

echo 로 찍어보면 해당 파일에서 분명히 세션이 생성된다.

echo (isset($_SESSION['userID']) ? $_SESSION['userID'] : "Visitor");

그런데 다른 파일에서 세션 정보 유지가 안된다.

환경설정에 가서
session.auto_start = 1

로 변경하고 나서야 세션 정보가 유지되었다.

 

 

참고 : 세션관련 참조하면 도움될 게시글

http://www.serverguide.co.kr/82

 

세션과 보안 : https://link2me.tistory.com/647 참조

728x90
블로그 이미지

Link2Me

,
728x90

PHP 에서 파일 인코딩을 검사하는 함수다.
구글신이 알려주길래 테스트 해봤더니 잘 되는거 같다.

다른 함수가 부정확할 수도 있다면서 나와 있길래 인코딩 검사를 해봤다.

C# 에서는 인코딩 검사하는 거 찾기 어렵던데 PHP에서는 쉽게 해결이 되는 거 같다.


function detectFileEncoding($filepath) {
    // 리눅스 기본 기능을 활용한 파일 인코딩 검사
    $output = array();
    exec('file -i ' . $filepath, $output);
    if (isset($output[0])){
        $ex = explode('charset=', $output[0]);
        return isset($ex[1]) ? $ex[1] : null;
    }
    return null;
}


728x90
블로그 이미지

Link2Me

,
728x90

jQuery를 이용해서 폼을 처리하기 위해서는, 'submit' 이벤트 리스너를 form 요소에 추가해야 한다.
$("form").on("submit", function() {
    // process form
});

$("form").submit(function(){
    // process form
});

폼 처리를 완전히 jQuery 내에서 한다면, 페이지를 다시 불러오는 것을 방지하기 위해 preventDefault()를 호출해야 한다.

$("form").on("submit", function(e) {
   e.preventDefault(); // 내장된 이벤트를 차단하는 명령
   // process form
});

$("form").submit(function(e){
    e.preventDefault(); 
// 내장된 이벤트를 차단하는 명령
    // process form
});



=== login.php ===

<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=yes, width=device-width" />
<title>Login Form</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<!-- Include the jQuery library -->
<script src="http://code.jquery.com/jquery.min.js" ></script>
<!--<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>-->
<script type="text/javascript" src="js/login.js"></script>
</head>
<body>
<div class="container">
    <section id="content">
        <form method="post" action="loginChk.php">
            <div>
                <input type="text" name="loginID" placeholder="아이디" required="" id="userid" />
            </div>
            <div>
                <input type="password" name="loginPW" placeholder="비밀번호" required="" id="password" />
            </div>
            <div>
                <input type="submit" value="로그인" />
            </div>
    </form><!-- form -->
    </section><!-- content -->
</div><!-- container -->
</body>

</html>

설명

method="post" 라고 지정한 부분을 생략하면 데이터 전송은 GET방식으로 처리된다. method="get" 이라고 지정해 줄 수도 있다.

GET방식으로 전송하면 URL의 파일명 뒤에 ? 를 명시한 뒤, key 와 value를 쌍으로 구성된 데이터가 포함될 수 있다.

전달할 수 있는 데이터의 총 크기는 1024 bytes 만 허용한다.

127.0.0.1/loginChk.php?loginID=test01&loginPW=1234 처럼 보이므로 보안에 취약하다.

key 인 loginID 는 <input> 태그의 name 속성에 지정한 값이 되고, value 는 <input> 태그의 value 속성값이 사용된다.



==== login.js ===

$(document).ready(function(){
    $("form").submit(function(e){
e.preventDefault(); // 내장된 이벤트를 차단하는 명령
        var loginID = $("#userid").val();
// var loginID = $("input[name='loginID']").val();
        var loginPW = $("#password").val();
 
        if( loginID =='') {
            alert("아이디를 입력하세요");
$("#userid").focus();
            return false;
        } 
        
        if(loginPW =='') {
            alert("패스워드를 입력하세요!");
$("#password").focus();
            return false;
        } 
        
    });

});


==== loginChk.php ===
PHP 5.5 이상에서는
$_POST['loginID'] 를 정확하게 입력해줘야 값을 인식한다.

PHP 버전이 낮은 경우에는 $_POST[loginID] 로 해도 값이 넘어가는데 높은 버전에서는 인식을 못하더라.


<?php
include_once 'dbconnect.php'; // 만드는 방법은 http://link2me.tistory.com/1110 참조
 
$workcode = LoginUserCheck(trim($_POST['loginID']),trim($_POST['loginPW']));
if($workcode == -1) {
    include "index.php";
else {
    // 로그인 후 처리할 내용 코드 입력
}
 
?>


jQuery 아이디 중복체크

http://link2me.tistory.com/1069


PHP 와 jQuery 값 전달이해
http://link2me.tistory.com/1124

728x90
블로그 이미지

Link2Me

,
728x90

순수하게 PHP 코드만 들어간 경우에는 가독성이 좋은 편이지만,

HTML 코드와 같이 섞여 있는 경우에는 가독성이 떨어진다.

게다가 초보자는 에러를 만나면 해결하기가 참 난해하다.

 

이럴 경우에는 PHP 대체 문법을 사용하여 코딩하는 것이 좋다.


PHP는 제어 구조를 위해 대체 문법을 제공한다.

if, while, for, foreach, switch.

각 경우에 대체 문법의 기본형태는 괄호열기를 콜른 (:)으로 대체하고

괄호닫기는 각각 endif;, endwhile;, endfor;, endforeach;, endswitch; 로 대체한다.

 

 

<?php $i=0while($R = db_fetch_array($RCD)):?>
<tr>
    <td><input type="checkbox" name="post_members[]" value="<?php echo $R['uid']?>" /></td>
<td class="name"><?php echo $R['classname']?></td>
<td class="name">
        <a href="<?php echo $url?>/?mod=modify&amp;where=<?php echo $where?>&amp;keyword=<?php echo urlencode($keyword)?>
&amp;p=<?php echo $p?>&amp;uid=<?php echo $R['uid']?>"
 class="b" title="수정"><?php echo $R['name']?></a>  
</td>
<td class="name"><?php echo $R['classname']?></td>
<td class="name"><?php echo $R['classname']?></td>
<td class="name"><?php if($R['memo']) echo ($R['memo'])?></td>
<td class="name"><?php echo number_format($R['income'])?></td>
<td class="name"><?php echo number_format($R['outgoings'])?></td>
<td class="date"><?php echo $R['date']?></td>
</tr> 
<?php $i++; endwhile;?> 
 

if/elseif 조건을 콜론을 사용해서 정의할 때, else if 처럼 두 단어로 나눠서는 안된다.
PHP는 처리 오류로 실패한다.

 

<?php
/* 부적합한 방법: */
if($a > $b):
    echo $a." is greater than ".$b;
else if($a == $b): // 컴파일 되지 않는다.   

    echo $a." equals ".$b;

endif;

/* 적합한 방법: */
if($a > $b):
    echo $a." is greater than ".$b;
elseif($a == $b): // 단어가 붙어 있는 점에 주의.
    echo $a." equals ".$b;
else:
    echo $a." is neither greater than or equal to ".$b;
endif;

?>

 

HTML Entities(엔티티)는 HTML 태그와 혼용되는 것을 막기 위해 브라우저 상에 예약된 문자를 사용한다.

특수 문자(참조 문자)를 써야 하는 경우에는 이러한 엔티티 코드로 변환해서 입력해야 한다.

변환하지 않고 특수 문자를 그대로 입력해 버리면 컴퓨터가 문서를 읽을 때 실제 문서 내용(contents)과 코드를 구분하기 못하는 문제가 발생하기 때문이다.
가령, 어떤 문서 내용에 꺽쇠 괄호 ' < '가 포함돼 있다면, 컴퓨터는 이 문서를 읽어들일 때 꺽쇠 괄호를 HTML 태그의 시작 기호로 받아들여 버린다.
또 큰따옴표 ' " '는 HTML 속성 값으로 인식될 수 있고, ' & '은 엔티티 기호의 시작으로 인식될 수 있다.
때문에 이러한 혼동을 막으려면 특수 문자 대신 각 문자의 엔티티 코드를 써야 한다. 가장 흔한 실수는 URL 주소에 포함된 ' & ' 기호를 그대로 쓰는 경우이다.

&nbsp; ” ” : 공백(스페이스 한 칸)을 의미
& is HTML for "Start of a character reference".
 &lt;  부등호(<)
 &gt;  부등호(>)
 &amp;  앰퍼샌드(&) 기호
 &quot;  쌍따옴표(“)
 &#035;  sharp(#)
 &#039;  따옴표(‘)

 

좀 더 자세한 내용은 https://www.w3schools.com/html/html_entities.asp 를 참조하면 도움된다.

 

실제 사용하는 예제를 살펴보자.

테이블 안에 HTML 태그 사이에 실제 입력될 값을 PHP 대체문법으로 처리하여 깔끔하고 에러없이 원하는 결과를 얻을 수 있다는 걸 알 수 있다.

 

<?php
require_once 'path.php';// root 폴더를 기준으로 상대적인 경로 자동 구하기
require_once $g['path_root'].'sessionChk.php';
require_once $g['path_config'].'dbconnect.php';
require_once $g['path_class'].'dbDataClass.php';
require_once $g['path_class'].'bbsClass.php';
$b = new bbsClass();
$d = new DBDataClass();
 
$link_url = "contacts.php"// 현재 실행중인 파일명 가져오기
$page = isset($_GET['page'])? trim($_GET['page']):1;//페이지 변수 설정
$rowsPage = 10// 한 화면에 표시되는 게시글 수
$curPage = isset($_GET['p']) ? $_GET['p'] : 1;
$m = isset($_GET['m']) ? $_GET['m'] :'list';
 
$flddata ="uid,cat1,cat2,mobileNO,officeNO";// 화면에 출력할 칼럼 발췌
$where = isset($_GET['where']) ? $_GET['where']: '';
$keyword = isset($_GET['keyword']) ? $_GET['keyword']: '';
$xorderbyisset($xorderby) ? $xorderby : 'cat1 ASC, cat2 ASC'// 없는 칼럼인지 꼭 체크하라.
 
$sqlque = 'display=1';
if ($cat1$sqlque .= ' and cat1='.$cat1;
if ($cat2$sqlque .= ' and cat2='.$cat2;
 
if($where && $keyword) {
    if($where == 'telNO') {
        $sqlque .= " and (mobileNO LIKE '%".$keyword."%' OR officeNO LIKE '%".$keyword."%') ";
    }
}
//echo $sqlque.'<br/>';
 
$g['url_link']=($m?'m='.$m.'&amp;':'').($where?'where='.$where.'&amp;':'').($keyword?'keyword='.urlencode(stripslashes($keyword)).'&amp;':'');
$g['bbs_reset'= $link_url.'?'.($m?'m='.$m.'&amp;':'');
 
$table ='members'// 테이블
$rows$d->getDbArray($table,$sqlque,$flddata,$xorderby,$rowsPage,$curPage);
$NUM = $d->getDbRows($table,$sqlque); // 전체 게시글수
$TPG = $b->getTotalPage($NUM,$rowsPage);
$i = 0;
?>
<div class="table-responsive text-nowrap">
<div class="float-left info">
    <?php if$keyword ):?><strong>"<?php echo $keyword?>"</strong> 검색결과 : <?php endif?>
    <?php echo number_format($NUM)?>개 (<?php echo $curPage;?>/<?php echo $TPG;?>페이지)
</div>
 
<table id="ListTable" class="table table-striped table-bordered table-hover" cellspacing="0" width="100%">
    <thead align='center'>
        <tr>
            <th scope="col">No</th>
            <th scope="col">구분1</th>
            <th scope="col">구분2</th>
            <th scope="col">휴대폰번호</th>
            <th scope="col">사무실번호</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach($rows as $R):?>
        <?php
            $CA1$d->getDbData('cate','id="'.$R['cat1'].'" and parent_id=0','name');
            $CA2$d->getDbData('cate','id="'.$R['cat2'].'" and parent_id="'.$R['cat1'].'"','name');
            $no = $NUM - (($curPage - 1* $rowsPage- $i;
            $i++;
        ?>
        <tr id="<?php echo $R['uid']; ?>">
            <td><?php echo $no;?></td>
            <td><?php echo $CA1['name'];?></td>
            <td><?php echo $CA2['name'];?></td>
            <td><a href="tel:<?php echo $R['mobileNO'];?>"><i class="fas fa-phone"></i></a></td>
            <td><a href="tel:<?php echo $R['officeNO'];?>"><i class="fas fa-phone"></i></a></td>
        </tr>
        <?php endforeach;?>
    </tbody>
</table>
 
<div class='form-group'>
    <form name="Form" class="form-inline" action="<?php echo $link_url;?>">
        <input type="hidden" name="m" value="<?php echo $m;?>" />
        <input type="hidden" name="cat1" value="<?php echo $cat1;?>" />
        <input type="hidden" name="cat2" value="<?php echo $cat2;?>" />
        <input type="hidden" name="orderby" value="<?php echo $xorderby;?>" />
 
        <div class="input-group mb-3">
            <select name="where" class="browser-default custom-select">
                <option value="telNO">전화번호</option>
            </select>
        </div>
        <div class="input-group mb-3">
          <input type="text" name="keyword" class="form-control" id="SearchKeyword">
          <div class="input-group-append">
            <button class="btn btn-md" type="button" id="Search">검색</button>
            <button class="btn btn-md" type="button" id="Home">Home</button>
          </div>
        </div>
    </form>
</div>
 
<?php $b->PageLinkView($link_url,$NUM,$rowsPage,$curPage,$g['url_link']);?>
</div>

 

 

 

<table id="AccessLogListTable" class="table table-striped table-bordered table-hover table-sm" cellspacing="0" width="100%">
    <thead align='center'>
        <tr>
            <th scope="col">No</th>
            <th scope="col">IP주소</th>
            <th scope="col">날짜</th>
            <th scope="col">시간</th>
            <th scope="col">OS</th>
            <th scope="col">Browser</th>
            <th scope="col">userID</th>
            <th scope="col">userNM</th>
            <th scope="col">성공/실패</th>
            <th scope="col">접속루트</th>
            <th scope="col">에러코드</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach($rows as $R):?>
        <?php
            $no = $NUM - (($curPage - 1) * $rowsPage) - $i;
            $i++;
        ?>
        <tr id="<?php echo $R['uid']; ?>">
            <td><?php echo $no;?></td>
            <td><?php echo $a->IPaddressMasking($R['ipaddr']);?></td>
            <td><?php echo $a->displayDate($R['date']);?></td>
            <td><?php echo $R['time'];?></td>
            <td><?php echo $R['OS'];?></td>
            <td><?php echo $R['browser'];?></td>
            <td><?php echo $a->IDMasking($R['userID']);?></td>
            <td><?php echo strlen($R['userNM'])>0 ? $a->letterMasking($R['userNM']):'';?></td>
            <td><?php echo $R['success'];?></td>
            <td><?php echo $R['route'];?></td>
            <td><?php echo $errorArr[$R['errCode']];?></td>
        </tr>
        <?php endforeach;?>
    </tbody>
</table>

 

728x90

'Web 프로그램 > PHP 문법' 카테고리의 다른 글

PHP Class 개념 이해 ★★  (0) 2017.01.10
PHP isset 과 empty 설명  (1) 2016.04.27
[PHP] switch 문  (0) 2015.06.01
[PHP] 문자열 자르기 substr  (0) 2015.05.16
음악 재생 1  (0) 2015.03.28
블로그 이미지

Link2Me

,
728x90
fgets(파일, 읽을 최대크기(바이트)); // 지정된 길이 만큼 읽어오되 \n을 만나면 종료한다.

fgetcsv( 파일, 읽을 최대크기(바이트), '구분자' ); // 파일에서 읽은 내용을 구분자로 나누어 배열로 저장

fread(파일, 임의의 길이(바이트)) ; 개행문자(\n)까지 길이로 인식한다.

파일 전체를 다 읽어 들이고 싶은 경우는 fread($fp,filesize($fp));

while ( !feof($fp) ) { //처리할 내용 }  // feof() 함수를 이용하면 끝까지 읽는다


<?php
$datafile = "1234.txt";
if(!file_exists($datafile))
{
    echo '<p>'.$datafile.' 파일이 없습니다</p>';
    exit;
}
 
$fp = fopen($datafile"r");
if ($fp) {
    while (($line = fgets($fp4096)) !== false// 한줄씩 읽어서 파일이 끝날때까지 loop
    {
        $tmp_array = explode"_" ,$line);  // 구분자를 기준으로 분할한 후 배열로
 
        for($i=0 ; $i < count($tmp_array- 1$i++) {
            $sub_array = explode(":",$tmp_array[1]); // 두번째 배열을 다시 분할한 후 배열로
            echo $line." --> "."변수 : ".$tmp_array[0]."_".$sub_array[0]." , value : ".$sub_array[1] ."<br>";
        }
    }
 
    if (!feof($fp)) {
        echo "Error: unexpected fgets() fail\n";
    }
}
 
fclose($fp);
?>



728x90
블로그 이미지

Link2Me

,
728x90
    데이터를 URL에 실어 GET방식으로 전송해야 할 때가 있다.
    GET 방식의 단점은 전달되는 변수와 값이 주소표시줄에 그대로 표시되므로
    데이터를 의도적으로 조작할 수 있다.
    urlencode() 함수는 이러한 문제점을 방지하기 위해 GET방식으로 URL에 실려 전달되는 데이터를 인코딩하는 함수이다.
    urlencode() 함수는 문자열만 적용된다.
    한글문자열은 헥사코드로 변환되고, 공백문자는 + 로 변환된다. 영문자는 변환되지 않고 그대로 전달된다.
    인코딩된 문자열을 전달받은 문서에서는 자동으로 디코딩이 이뤄진다.
    따라서, 인코딩된 문자열을 디코딩하기 위해 urldecode() 함수를 사용할 필요는 없다.


    테이블에 존재하는 특정 레코드들 중 특정 단어를 포함하는 레코드를 검색하고자 하는 경우 해당 검색어를 GET방식으로 문서에 전달하게 된다. 이 경우 전달되는 검색어는 반드시 urlencode() 함수로 인코딩해 전달해야 한다.

    한글이 입력될 가능성이 있는 부분엔 반드시 urlencode() 함수로 인코딩하여 처리한다고 생각하면 된다.


    GET 방식이 아닌 POST 방식으로 전달되는 경우, urlencode() 함수로 인코딩하면 반드시 urldecode()함수로 디코딩해주어야 원래의 문자열을 확인할 수 있다.


    Login 시 사용하는 userID, userPW 정보는 네트워크 상에서 스니핑 툴로 정보를 알아낼 수가 있다.

    이 경우에는 userID, userPW 정보도 암호화해서 보내고 서버에서 암호를 풀어서 사용자 식별을 해야 한다.

    (서버에서 패스워드 정보는 암호화되므로 암호화된채로 비교 검사)

    urlencode 를 했다고 해서 정보가 안보이는게 아니라는 것을 꼭 알아야 한다. 영문, 숫자 등은 그대로 보인다.

    단지 한글 정보만 헥사값을 변경된다는 것일 뿐이다.

    자바스크립트 암호화로 구글링을 검색하면 많이 나온다.


728x90
블로그 이미지

Link2Me

,
728x90

게시판에서 본문을 입력하는 내용은 줄바꿈을 하면서 자료를 입력하게 된다.

DB에서는 자료를 어떻게 저장할까?
사용자가 엔터키를 사용해 문자열을 입력했다고 해도 DB에 저장될 때는 한 라인으로 저장된다.

사용자가 입력한 엔터키는 개행문자(\n)로 대치되어 저장된다.

phpMyAdmin 에서 해당 게시물을 조회하고 해당 게시물에 직접 들어가서 저장된 텍스트 내용을 확인해 보면 알 수 있다.


DB에 존재하는 한 라인 이상의 문자열을 Web browser 의 화면에 출력하면 출력이 될까?

안된다. 이유는?


HTML 문서는 개행문자(\n)를 인식하지 못한다.

HTML 문서는 <br> 태그나 <p> 태그에 의해서만 라인이 구분된다.


Web browser 의 화면에 출력하기 위해서는 반드시 nl2br()함수를 사용해 개행문자(\n)를 <br> 태그로 변환해야 한다.

nl2br()함수는 문자열 내에 개행문자(\n)가 존재한다면 모든 개행문자를 <br>태그로 변환한다.


그러므로 보통 DB에 저장할 때 nl2br()함수를 이용해서 개행문자(\n)를 <br>로 저장한다.


입력된 글에 인용부호나 특수문자가 들어간 경우에는 각 문자 앞에 역슬래쉬(\)를 추가하는 addslashes() 함수를 적용해야 한다.

화면에 출력하는 경우 반드시 stripslashes() 함수를 먼저 적용하고 나중에 nl2br()함수를 적용해야 한다.

stripslashes() 함수는 addslashes() 함수를 통해 표기된 \ 문자를 원래대로 돌려준다.


텍스트 파일이나 CSV 파일을 읽어서 DB에 있는 자료와 중복 여부를 체크해야 하는 경우

문자열에 싱글쿼테이션이 들어가 있다면 어떻게 해야 할까?

DB에는 이미 addslashes() 함수를 적용해서 싱글쿼테이션 문자 앞에 역슬레쉬(\) 문자가 추가되어 있다.

따라서, Select * FROM 테이블명 Where eng =' addslashes($line[2])' 를 해야 한다.


728x90
블로그 이미지

Link2Me

,
728x90

킴스큐 RB를 이해하는데 도움이 되도록 함수에 설명을 좀 추가하고 있다.


<?php
function isConnectDb($db)
{
    $conn = mysql_connect($db['host'].':'.$db['port'],$db['user'],$db['pass']);
    $selc = mysql_select_db($db['name'],$conn);  // 접근한 계정으로 사용할 수 있는 DB 선택
    // 연결 식별자($conn) 는 생략 가능하며, 생략시 가장 최근에 설정한 연결 식별자가 사용된다.
    return $selc ? $conn : false;
}
function db_query($sql,$con)
{
    mysql_query('set names utf8',$con);
    mysql_query('set sql_mode=\'\'',$con);
    // 연결 식별자($conn) 는 생략 가능하며, 생략시 가장 최근에 설정한 연결 식별자가 사용된다.
    return mysql_query($sql,$con);
}
function db_fetch_array($que)
{
    // @는 PHP에서 수행에 지장이 없는 경고 메시지가 나타나지 않도록 하는 기호
    // 결과 레코드 집합에서 한 레코드를 가져와 배열을 생성한다.
    // mysql_fetch_array() 함수가 호출되면 결과 레코드 집합 식별자는 자동으로 다음 레코드로 이동된다
    return @mysql_fetch_array($que);
}
function db_fetch_assoc($que)
{

    // 가장 많이 사용되는 함수로써 키값을 가지고 데이터를 출력한다
    return mysql_fetch_assoc($que);
}
function db_num_rows($que)
{
    return mysql_num_rows($que);
}
function db_info()
{
    return mysql_get_server_info();
}
function db_error()
{
    // 오류의 내용을 문자열로 반환하는 함수
    return mysql_error();
}
function db_close($conn)
{
    // DB 접속을 종료하는 기능을 수행한다.
    // mysql_close() 함수를 반드시 호출해야만 DB 연결이 종료되는 것은 아니다.
    // 해당 PHP 스크립트의 수행이 종료됨과 동시에 DB와의 접속은 자동 종료된다.
    return mysql_close($conn);
}
function db_insert_id($conn)
{
    return mysql_insert_id($conn);
}
//DB-UID데이터
function getUidData($table,$uid)
{
    return getDbData($table,'uid='.(int)$uid,'*');
}
//DB데이터 1ROW
function getDbData($table,$where,$data)
{
    $row = db_fetch_array(getDbSelect($table,getSqlFilter($where),$data));
    return $row;
}
//DB데이터 ARRAY
function getDbArray($table,$where,$data,$sort,$orderby,$recnum,$p)
{
    global $DB_CONNECT;
    $rcd = db_query('select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):'').' order by '.$sort.' '.$orderby.($recnum?' limit '.(($p-1)*$recnum).', '.$recnum:''),$DB_CONNECT);
    return $rcd;
}
//DB데이터 NUM
function getDbRows($table,$where)
{
    global $DB_CONNECT;
    $rows = db_fetch_array(db_query('select count(*) from '.$table.($where?' where '.getSqlFilter($where):''),$DB_CONNECT));
    return $rows[0] ? $rows[0] : 0;
}
//DB데이터 MAX
function getDbCnt($table,$type,$where)
{
    global $DB_CONNECT;
    $cnts = db_fetch_array(db_query('select '.$type.' from '.$table.($where?' where '.getSqlFilter($where):''),$DB_CONNECT));
    return $cnts[0] ? $cnts[0] : 0;
}
//DB셀렉트
function getDbSelect($table,$where,$data)
{
    global $DB_CONNECT;
    $r = db_query('select '.$data.' from '.$table.($where?' where '.getSqlFilter($where):''),$DB_CONNECT);
    return $r;
}
//DB삽입
function getDbInsert($table,$key,$val)
{
    global $DB_CONNECT;
    db_query("insert into ".$table." (".$key.")values(".$val.")",$DB_CONNECT);
}
//DB업데이트
function getDbUpdate($table,$set,$where)
{
    global $DB_CONNECT;
    db_query("update ".$table." set ".$set.($where?' where '.getSqlFilter($where):''),$DB_CONNECT);
}
//DB삭제
function getDbDelete($table,$where)
{
    global $DB_CONNECT;
    db_query("delete from ".$table.($where?' where '.getSqlFilter($where):''),$DB_CONNECT);
}
//SQL필터링
function getSqlFilter($sql)
{
    return $sql;

    // preg_replace("/찾을 문자열/" , "변경할 문자열" , "해당 문자열");
    // /찾을 문자열/ 에서 / 는 정규식의 시작과 끝을 알린다.
}
?>


=======================================================================

mysql_fetch_row()
인덱스 번호로만 데이터를 출력한다.
가장 빠르다고 알려져 있으나 어느 컬럼을 가져왔는지 가독성이 떨어저 많이 이용하지 않는다.

$query = 'SELECT * FROM table_name';
$result = mysql_query($query);
while($row = mysql_fetch_row($result)){
echo $row[0] .'<br>';
}
mysql_close($db);

mysql_fetch_assoc()
가장 많이 사용되는 함수로써 키값을 가지고 데이터를 출력한다.

$query = 'SELECT * FROM table_name';
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)){
echo $row['uid'] .'<br>';
}
mysql_close($db);

mysql_fetch_array()
이 함수는 인덱스(숫자)번호와 연관 배열의 키값으로 데이터를 가져 올 수 있다.

$query = 'SELECT * FROM table_name';
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
echo $row['uid'] .'<br>';
}
mysql_close($db);

728x90
블로그 이미지

Link2Me

,
728x90

PHP 파일 업로그 관련 함수와 예제를 간단하게 작성해봤다.


리눅스에서 APM(Apache, PHP, MySQL) 소스 설치를 여러번 연습하다보니 php.ini 환경설정 변수 설정이 중요하다는 걸 알게 되었다.

파일 업로드를 위해서 php.ini 설정을 수정해줘야 한다.

기본 설치를 하면 파일 업로드 용량이 작게 설정되어 있다.

file_uploads = on  // PHP 를 사용해서 파일 업로드를 허용할 것인지를 결정하는 항목

upload_tmp_dir=  // 이 항목에 값을 지정하지 않으면 시스템이 사용하는 임시 디렉토리를 사용하게 됨

upload_max_filesize = 50M   // 업로드되는 파일의 최대 크기를 지정하는 항목

post_max_size = 60M  // 파일은 POST 방식으로 서버에 전달. upload_max_filesize 보다 반드시 커야 한다.



bool is_uploaded_file(filename) 함수는 파일 업로드 양식을 통해 파일이 POST 방식으로 업로드되었는지 여부를 조사하는 함수이다.

is_uploaded_file() 함수의 인자는 실제 파일 이름이 아니라 임시 디렉토리에 존재하는 임시 파일 이름이다.


bool move_uploaded_file(임시파일명, 실제파일명);

임시 디렉토리에 업로드된 파일을 새로운 디렉토리로 이동시킨다.

먼저 임시 디렉토리를 조사하여,

- 업로드된 파일이 존재하지 않으면 False를 반환한다.

- 파일은 존재하지만 지정된 위치로의 이동이 실패하면 False를 반환한다.


bool file_exists(realname);

파일명(realname)이 존재하는지 조사하여 존재하면 True, 없으면 False 를 반환한다.

이 함수는 파일을 업로드할 때 서버에 동일한 이름의 파일이 존재하는지 조사하기 위해 주로 사용한다.

filename 은 파일명 자체를 의미하지 않고, 실제 업로드할 파일 경로 + 파일명을 의미한다.

$filepath_name = "../files" . "/" . $realname;

if( file_exists($filepath_name)) {

    echo '동일한 이름을 가진 파일이 존재합니다';

    exit;

}


스크립트 언어는 실행엔진만 서버에 적재되어 있다면 언제든 실행이 가능하다.

보안을 위협할 수 있는 코드가 삽입된 스크립트 문서나 실행 가능한 파일이 업로드 되지 않도록 해야 시스템의 보안 문제를 방지할 수 있다.


========= Form 데이터 파일 =================

// PHP 에서 파일을 업로드 하는 경우 업로드되는 파일은 반드시 POST 방식으로 전달되어야 한다.

// 파일을 첨부하기 위해서는 <form> 태그에 enctype 속성의 값으로 "multipart/form-data"를 지정해야 한다.
<form name="procForm" method=POST action="addresswrite.php" enctype="multipart/form-data" onsubmit="return saveCheck(this);">
    <input type=file name="excel" size=30 /><br /><br />
    <input type=submit value="전송" />
</form>

<script type="text/javascript">
//<![CDATA[
function saveCheck(f)
{
    if (f.excel.value == '')
    {
        alert('CSV 파일을 선택해 주세요.');
        f.excel.focus();
        return false;
    }
}
//]]>
</script>

========== addresswrite.php =====================
<?php
// POST 방식으로 전달받은 파일을 검사하여 업로드 및 파일 read 하여 DB에 데이터 저장 처리
$tmpname    = $_FILES['excel']['tmp_name'];  // 임시파일명

if (is_uploaded_file($tmpname))  // 임시파일이 디렉토리에 존재하는 경우
{

    $realname    = $_FILES['excel']['name'];  // 실제 파일명
    $filesize    = $_FILES['excel']['size']; // 파일 크기
    $filetype    = $_FILES['excel']['type']; // 파일 형태
    $fileExt    = strtolower(getExt($realname));  // 파일 확장자 구하는 함수

    $saveFile    = $g['dir_module'].'files/csv/'.$csvfile;

    if (!strstr('[csv][xlsx]',$fileExt))   // 업로드 가능 확장자 조사
    {
        getLink('','','csv, xlsx 파일만 등록할 수 있습니다.','');
    }

    // 동일한 이름을 가진 파일이 존재하는 지 검사, unlink 하여 파일을 지우지 않을 경우

    // if(file_exists($saveFile))
    move_uploaded_file($tmpname,$saveFile);  // 임시 디렉토리에 있던 파일을 실제 파일의 이름으로 전송

    @chmod($saveFile,0606);  // 리눅스에서 파일 권한 변경
}

// 파일을 업로드한 후 파일을 연다
$file=fopen($saveFile,"r");
if(!$file){
    echo("Failed to open the file");
    exit;
}

while($line = fgetcsv($file,1000, ";")) { // 구분자는 ; 로 지정, 한줄씩 읽어드린 값을 마지막행까지 계속하라.
    $line0    = iconv("euc-kr", "utf-8", $line[0]); // 파일의 인코딩 모드가 ANSI 일 경우 UTF8 로 변경처리
    $line1    = iconv("euc-kr", "utf-8", $line[1]);
    // 구분자로 분리해서 읽어들인 항목을 DB의 칼럼에 대입하여
    // 신규 등록 또는 기존 자료 중복체크 등을 수행한다.
}
fclose ($file);   // 성공하면 1을 반환하고 실패하면 0을 반환
unlink($saveFile);  // 업로드한 실제 파일 삭제
// 등록건수 및 중복건수 팝업창 보여주기
?>

728x90
블로그 이미지

Link2Me

,
728x90

킴스큐 RB 1.2 파일에 매번 동일한 함수를 추가하는 것은 불합리한 거 같아서

core 폴더에 함수를 추가했다.


function add_hyphen_telNo($tel)
{
    $tel = preg_replace("/[^0-9]/", "", $tel);    // 숫자 이외 제거
    if (substr($tel,0,2)=='02')
        return preg_replace("/([0-9]{2})([0-9]{3,4})([0-9]{4})$/", "\\1-\\2-\\3", $tel);
    else if (substr($tel,0,3)=='050')  // 평생번호
        return preg_replace("/([0-9]{4})([0-9]{3})([0-9]{4})$/", "\\1-\\2-\\3", $tel);
    else if (strlen($tel)=='8' && (substr($tel,0,2)=='15' || substr($tel,0,2)=='16' || substr($tel,0,2)=='18'))
        // 지능망 번호이면
        return preg_replace("/([0-9]{4})([0-9]{4})$/", "\\1-\\2", $tel);
    else
        return preg_replace("/([0-9]{3})([0-9]{3,4})([0-9]{4})$/", "\\1-\\2-\\3", $tel);
}


전화번호 표시를 자동으로 깔끔하게 표시하고 싶어서다.


파일에서는

<?php include_once $g['path_core'].'/function/string.func.php';?>

한줄만 추가해주고 나서 해당 전화번호를 표시할 부분에

<tr height=25>
    <td class="td1">휴대폰</td>
    <td class="td2"><?php echo add_hyphen_telNo($R['cellphone'])?></td>
</tr>


로 해주면 보기좋게 하이픈이 들어가서 표시된다.




728x90
블로그 이미지

Link2Me

,
728x90

킴스큐 사이트내에서 정보 찾아내려면 힘든 경우가 있어서 편리하게 찾아서 활용하고 싶어서 변수 저장 정보를 적어둔다.


<?php
$g = array(
    'path_root'   => './',
    'path_core'   => './_core/',
    'path_var'    => './_var/',
    'path_tmp'    => './_tmp/',
    'path_layout' => './layouts/',
    'path_module' => './modules/',
    'path_widget' => './widgets/',
    'path_switch' => './switchs/',
    'path_page'   => './pages/',
    'path_file'   => './files/',
    'sys_lang'    => 'korean'
);

$g['path_root']  = './';   // 파일 위치에 따라
$g['path_core']  = $g['path_root'].'_core/';
$g['path_var']  = $g['path_root'].'_var/';
$g['img_layout'] = './layouts/default/image'; // 이미지 경로때문에 임의추가
$g['files_layout'] = './layouts/default/files'; // 외부페이지 경로 임의추가


include_once $g['path_var'].'db.info.php';
include_once $g['path_var'].'table.info.php';
include_once $g['path_core'].'function/db.mysql.func.php';
include_once $g['path_var'].'db.info.php';
include_once $g['path_var'].'table.info.php';
include_once $g['path_core'].'function/db.mysql.func.php';
include_once $g['path_core'].'function/sys.function.php';
include_once $g['path_core'].'function/string.function.php';

define('__KIMS__',true);
error_reporting(E_ALL ^ E_NOTICE);
session_save_path($g['path_root'].'_tmp/session');
session_start();

$DB_CONNECT = isConnectDb($DB);
$my = array();
if ($_SESSION['mbr_uid'])
{
 $my = getUidData($table['s_mbrid'],$_SESSION['mbr_uid']);
 $my = array_merge(getDbData($table['s_mbrdata'],"memberuid='".$my['uid']."'",'*'),$my);
 if($my['pw'] != $_SESSION['mbr_pw']) exit;
}

?>


킴스큐 구조 파악을 위한 매뉴얼 http://www.kimsq.co.kr/r/freeboard/13482

728x90
블로그 이미지

Link2Me

,
728x90

킴스큐RB 1.2 에서 정해준 폴더에 출력하는 것이 아니라 완전 다른 폴더에서 별도로 만드는 게시판을 연동하는 경우를 테스트해봤다.

모양 출력 제대로 보이게 하는 것은 생락하고 화면에 출력되는 것만 보기 위해서다.

연동에 필요한 함수는 더 필요한 것을 찾아서 넣어야겠지만 기본적으로는 아래 4개 정도면 될거 같다.

테이블명은 직접 테이블명을 적어줘여 한다.


<?php
########## KIMSQRB와 연동된 로그인 정보 가져오기 ##########
defined('__KIMS__');
include_once '../_var/db.info.php';
include_once '../_core/function/db.mysql.func.php';
include_once '../_core/function/sys.func.php';
include_once '../_core/function/lib/getContent.lib.php';

$DB_CONNECT = isConnectDb($DB); // 데이터베이스 연결하기 완료

$sqlque = 'display=1';

$RCD = getDbArray('rb_guide_data',$sqlque,'*','uid','desc',0,1);
$NUM = getDbRows('rb_guide_data',$sqlque);
$TPG = getTotalPage($NUM,10);

echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
echo $NUM;  // 게시물 개수
echo $TPG;  // 페이지 출력수
echo '<table border=1>';
echo '<tr>';

$i=1;
while ($R = db_fetch_array($RCD)){
    $_CAT1 = getUidData('rb_guide_category',$R['category1']);

    echo '<td ALIGN=CENTER>'.$i.'</td>';
    echo '<td ALIGN=CENTER>'.$_CAT1['classname'].'</td>';
    echo '<td>'.$R['eng'].'</td>';
    echo '<td>'.$R['kor'].'</td>';
    echo '<td>'.$R['kor'].'</td>';
    echo '<td>'.$R['kor1'].'</td>';
    echo '<td>'.$R['kor2'].'</td>';
    echo '<td>'.$R['kor3'].'</td>';
    echo '<td>'.LIB_getContents($R['content'],$R['html']).'</td>';
    echo '</tr>';
    $i++;
}
echo '</table>';
exit;

?>



728x90
블로그 이미지

Link2Me

,
728x90

자바스크립트에서 값이 참일 경우에만 폼 전송이 이루어지게 하는 예제이다.


<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<script language="JavaScript">
function send(f) {
    if (confirm('폼의 값을 전송할까요?')==1) {
        f.submit();
        window.close();
    }
}
</script>
</HEAD>
<BODY>
<form name=bbsSearch action= "http://www.naver.com">
<input type=button value="보내기" onClick=send(this.form) >
</form>
</BODY>
</HTML>


설명

조건문에서 1은 참(true), 0 은 거짓(false)을 나타낸다.

send(form) 에서 f 은 호출할 때 전달받은 인자(객체, 값 등)를 담은 함수의 매개변수다.

onClick=send(this.form) 에서 this.form 이 send 함수의 f 변수에 담겨진다.

var f = <form name=bbsSearch action= "http://www.naver.com"> 와 같은 의미다.

하지만 자바스크립트에서는 위와 같이 적어 사용할 수 없고

this.form 대신에 직접 객체를 찾아 대입한다면

var f=document.forms['bbsSearch'];  // form 중 이름이 bbsSearch 인 form 객체를 변수 f 에 대입

처럼 사용해야 한다.


onSubmit="return checkForm(this)" → 폼 전송이 이루어지기 전에 먼저 checkForm(this) 함수를 실행하고, 함수실행 결과로 전달 받은 값이 false라면 폼전송을 하지 않고, true라면 폼 전송을 해라.


자바스크립트 로그인 예제 파일이다. 첨부파일은 하단에 있으니 받아서 테스트해보면 된다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="form1.css"  />
</head>
<body>
<script>
function validateForm(){
    var sform = document.forms["s_form"];
    if(!sform.loginID.value){
        alert('아이디를 입력하세요');
        sform.loginID.focus();
        return false;
    }
    if(sform.loginPW.value ==''){
        alert('패스워드를 입력하세요');
        return false;
    }
}
</script>
<div class="container">
<h2>Form 예제1</h2>
<form name="s_form" method="post" action="form1.action.php" onsubmit="return validateForm();">
    <table>
        <tr>
            <td>로그인 ID</td>
            <td><input type="text" name="loginID" value=""></td>
        </tr>
        <tr>
            <td>패스워드</td>
            <td><input type="password" name="loginPW"></td>
        </tr>
        <tr>
            <td colspan='2' align='center'><input type="submit" value="전송"></td>
        </tr>
    </table>
</fom>
</div>
</body>
</html>


아래 예제는 전송 버튼에 onclick 를 추가해서 시도해본 예제다.

<form name="s_form" method="post" action="#"> 기본 action 경로를 파일명으로 지정하지 않고도 자바스크립트에서 추가해서 보낼 수 있다는 걸 확인할 수 있다.

만약 <form name="s_form" action="#"> 와 같이 method 방식을 지정하지 않으면 default 인 method="get" 으로 동작된다는 것도 알아두자.

자바스크립트 코드에서 sform.method = "post"; 를 추가해주면 POST 방식으로 전송된다.

즉, 이 예제는 Form 의 기본 속성을 자바스크립트가 제어할 수 있다는 걸 보여주는 예제이다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="form1.css"  />

</head>
<body>
<script>
function validateForm(){
    var sform = document.forms["s_form"];
    if(!sform.loginID.value){
        alert('아이디를 입력하세요');
        sform.loginID.focus();
        return false;
    }
    if(sform.loginPW.value ==''){
        alert('패스워드를 입력하세요');
        sform.loginPW.focus();
        return false;
    }
    sform.method = "post";
    sform.action = "form1.action.php"; // 이 줄을 주석처리하면 어떤 결과가 될까?
}
</script>
<div class="container">
<h2>Form 예제2</h2>
<form name="s_form" method="post" action="#">
    <table>
        <tr>
            <td>로그인 ID</td>
            <td><input type="text" name="loginID" value=""></td>
        </tr>
        <tr>
            <td>패스워드</td>
            <td><input type="password" name="loginPW"></td>
        </tr>
        <tr>
            <td colspan='2' align='center'><input type="submit" value="전송" onclick="return validateForm();"></td>
        </tr>
    </table>
</fom>
</div>
</body>
</html>


여기서 onclick="return validateForm();" 대신에 onclick="validateForm();" 로 하면 어떤 현상이 발생할까?

아래에서 첫번째 것은 아이디, 패스워드 등을 물어보는 팝업창이 한번 뜨고 form 전송 이벤트가 바로 실행되는 걸 확인할 수 있을 것이다.

두번째 것은 form action 을 자바스크립트에서 지정해주었기 때문에 순차 실행을 하다가 return false 를 실행하고 나서 form action 을 실행할 수가 없기 때문에 화면이 action 파일명으로 넘어가지 못한다.

sform.action = "form1.action.php"; 를 if 조건문 위쪽에 적었다면 팝업창을 띄워 입력값을 확인하지만 값이 입력되지 않았음에도 불구하고 실행된다는 걸 확인할 수 있다.

<form name="s_form" method="post" action="form1.action.php">

<script>
function validateForm(){
    var sform = document.forms["s_form"];
    if(!sform.loginID.value){
        alert('아이디를 입력하세요');
        sform.loginID.focus();
        return false;
    }
    if(sform.loginPW.value ==''){
        alert('패스워드를 입력하세요');
        sform.loginPW.focus();
        return false;
    }
}
</script>

<form name="s_form" method="post">

<script>
function validateForm(){
    var sform = document.forms["s_form"];
    if(!sform.loginID.value){
        alert('아이디를 입력하세요');
        sform.loginID.focus();
        return false;
    }
    if(sform.loginPW.value ==''){
        alert('패스워드를 입력하세요');
        sform.loginPW.focus();
        return false;
    }
    sform.method = "post";
    sform.action = "form1.action.php";
}
</script>


jsfrm1.zip



도움이 되셨다면 00 00 해 주세요.

728x90
블로그 이미지

Link2Me

,
728x90

PHP 에서 버그찾기가 참 힘들다.

C# 에서는 프로그램이 버그이면 메시지를 뿌려주니까 그 부분을 집중적으로 살펴보면 되는데 PHP는 에러가 발생한 곳을 찾아내기가 힘들다.

내가 뭔가 세팅을 잘못하고 있는 부분이 있는가 보다.


관리자 모드에서는 동작이 정상적으로 되는데 사용자 모드에서 동작이 안되길래 너무 이상하다고 버그 잡기에 나섰는데 킴스큐 RB 구조를 완벽하게 이해를 못하니까 버그 잡기가 쉽지 않다.

list.php 파일이 잘못되었나 살펴봐도 이상이 없다.

main.php 파일을 한줄 한줄 살펴보면서 원인을 찾아냈다.

if (!$my['admin']){
       $sqlque .= ' and hidden=0';
}

원인은 이거였다.

테이블을 설계하면서 hidden 필드 자체가 불필요해서 없애버렸다.

필드가 없으니까 당연히 에러가 보여야 되는데 화면에서는 데이터가 없다고만 나온다. ㅋㅋ

C# 이라면 필드 자체가 없으니까 에러가 나왔을 것인데 에러가 나오지를 않았다.

에러메시지 출력하라는 옵션을 제거해서 그런가??

아무튼 집중적으로 에러 잡는 방법을 배워야겠다.

로직 설계 부분에서는 아무런 문제가 없는데 나중에 한줄 한줄 확인하다보면 특정한 곳에서 발생하는 에러 때문에 문제가 생기는 거 같다.

728x90
블로그 이미지

Link2Me

,
728x90

Web 에서 버그가 생기면 찾아내기가 쉽다고 해서 피들러를 배워보려고 한다.


피들러

- 보내는 요청이나 들어오는 응답을 조작 가능

- 요청이나 응답에 중단점(breakpoint) 를 설정하여 트래픽을 수동으로 조작 가능

- 서버의 응답을 모두 수집한 뒤에 클라이언트로 데이터를 내보낸다.

- HTTPS 트래픽을 복호화하여 살펴보거나 수정하는 것도 가능하다.

- PC, 스마트폰에서 발생하는 웹 트래픽을 디버깅할 수 있다.

- 2G 미만의 요청/응답만 다룰 수 있다.





728x90
블로그 이미지

Link2Me

,
728x90

workcode workcode Query


select a.uid, a.id, b.name, b.nic, b.level, a.workcode from rb_s_mbrid a, rb_s_mbrdata b where a.uid=b.memberuid and a.workcode > 0 order by a.workcode desc;












728x90

'Web 프로그램 > 킴스큐RB' 카테고리의 다른 글

킴스큐 폴더를 벗어난 폴더에서 PHP 함수 출력  (1) 2016.03.08
버그 찾기 힘들다  (0) 2016.02.15
킴스큐 RB2 게시판 생성  (0) 2015.09.30
RB2 Layout 설정  (0) 2015.08.20
킴스큐 RB2 모듈 삭제 방법  (0) 2015.08.01
블로그 이미지

Link2Me

,
728x90

킴스큐 RB2 게시판 생성이 어떻게 되는지 순서를 알아두고 싶어서 적어둔다.


1. 관리자 모드에서 게시판을 생성한다.




2. 게시판이 생성되면 rb_bbs_list 테이블에 정보가 기록된다.





rb_bbs_data 에 게시글이 추가된다.

추가될 때 rb_bbs_list 에 생성된 테이블의 gid => bbs, id => bbsid 로 매핑되는 걸 확인할 수 있다.



게시판과 메뉴 연결



728x90

'Web 프로그램 > 킴스큐RB' 카테고리의 다른 글

버그 찾기 힘들다  (0) 2016.02.15
[SQL] 회원정보 중에서 필요한 거 뽑아보기  (0) 2015.09.30
RB2 Layout 설정  (0) 2015.08.20
킴스큐 RB2 모듈 삭제 방법  (0) 2015.08.01
[RB1] 회원테이블 이전시  (0) 2015.07.27
블로그 이미지

Link2Me

,